2015-09-17 4 views
7

数値シーケンスのリストに基づいて、data.frameから行を簡単にフィルタリングする方法を探しています。リストから共通の値に基づいてdata.frameから行を抽出する

ここexempleです:

私の最初のデータフレーム:

data <- data.frame(x=c(0,1,2,0,1,2,3,4,5,12,2,0,10,11,12,13),y="other_data") 

マイリスト:

list1 <- list(1:5,10:13) 

私の目標は、正確に含まれている "データ" から行のみを維持することです"data"の "x"列と同じ "list1"の数字列。 ので、出力data.frameは次のようになります。これを行うための

finaldata <- data.frame(x=c(1:5,10:13),y="other_data") 

任意のアイデア?

+0

'c(" other_data "、" data "、rep(" other_data "、14))'? –

+0

'data < - data.frame(x = c(0,1,2,0,1,2,3,4,5,12,2,0,10,11,12,13)、y =手紙[1:16])を例として、期待される結果を示しています。 – Roland

答えて

2

、それはlapplyに拡張することは簡単です。

#function that takes sequence and a vector 
#and returns indices of vector that have complete sequence 
get_row_indices<- function(sequence,v){ 
    #get run lengths of whether vector is in sequence 
    rle_d <- rle(v %in% sequence) 
    #test if it's complete, so both v in sequence and length of 
    #matches is length of sequence 
    select <- rep(length(sequence)==rle_d$lengths &rle_d$values,rle_d$lengths) 

    return(select) 

} 


#add row ID to data to show selection 
data$row_id <- 1:nrow(data) 
res <- do.call(rbind,lapply(list1,function(x){ 
    return(data[get_row_indices(sequence=x,v=data$x),]) 
})) 

res 

> res 
    x   y row_id 
5 1 other_data  5 
6 2 other_data  6 
7 3 other_data  7 
8 4 other_data  8 
9 5 other_data  9 
13 10 other_data  13 
14 11 other_data  14 
15 12 other_data  15 
16 13 other_data  16 
+0

ありがとうございました。あなたのカスタム関数はうまく動作します:) – jeff6868

1

zooからrollapplyを使用していない理由:私は1つのシーケンスのためのサブセットを取得するために、カスタム関数で開始

library(zoo) 

ind = lapply(list1, function(x) { 
    n = length(x) 
    which(rollapply(data$x, n, function(y) all(y==x))) + 0:(n-1) 
}) 

data[unlist(ind),] 
#x   y 
#5 1 other_data 
#6 2 other_data 
#7 3 other_data 
#8 4 other_data 
#9 5 other_data 
#13 10 other_data 
#14 11 other_data 
#15 12 other_data 
#16 13 other_data 
+0

私はこのような感謝の言葉が落胆しているのを知っていますが、しばらくの間rollapplyでそれを作る方法には苦労していました。 – Tensibai

+0

Np私は(私の視点から)未知のものを使って、 ! –

0

機能match2x値を通過し、長さnのベクトルに対してそれと次のn個の値をチェックします。次に、Reduceを使用してインデックス作成のシーケンスを作成します。これにより

match2 <- function(vec) { 
    start <- which(sapply(1:nrow(data), function(i) all(data$x[i:(i+length(vec)-1)] == vec))) 
    Reduce(':', c(start,start+length(vec)-1)) 
} 

、我々は各list1するためのプロセスを繰り返すために適用する機能を使用することができます。

s <- sapply(list1, match2) 
data[unlist(s),] 
#  x   y 
# 5 1 other_data 
# 6 2 other_data 
# 7 3 other_data 
# 8 4 other_data 
# 9 5 other_data 
# 13 10 other_data 
# 14 11 other_data 
# 15 12 other_data 
# 16 13 other_data 
1
extract_fun <- function(x, dat){ 
    # Index where the sequences start 
    ind <- which(dat == x[1]) 
    # Indexes (within dat) where the sequence should be 
    ind_seq <- lapply(ind, seq, length.out = length(x)) 
    # Extract the values from dat at the position 
    dat_val <- mapply(`[`, list(dat), ind_seq) 
    # Check if values within dat == those in list1 
    i <- which(as.logical(apply(dat_val, 2, all.equal, x))) # which one is equal? 
    # Return the correct indices 
    ind_seq[[i]] 
} 

結果

all_ind <- do.call(c, lapply(list1, extract_fun, data$x)) 
data[all_ind,] 

list1で項目ごとのインデックスを取得し、必要に応じてインデックスにそれらを結合:列 `y`場合所望の出力が何であるかを

x   y 
5 1 other_data 
6 2 other_data 
7 3 other_data 
8 4 other_data 
9 5 other_data 
13 10 other_data 
14 11 other_data 
15 12 other_data 
16 13 other_data 
関連する問題