2017-03-24 9 views
3

質問が重複していても、stackoverflowで検索しても解決策が得られないのかどうかはわかりません。文字の順序付きベクトルに基づいてデータフレームの行をフィルタリングする

私は、次のデータフレームで得られた文字列に(この順序で)ワードBINGOを形成するだけの行を選択したい、次のデータフレーム

num char 
1  A 
2  K 
3  I 
4  B 
5  I 
6  N 
7  G 
8  O 
9  Z 
10 Q 

を有する:

num char 
4  B 
5  I 
6  N 
7  G 
8  O 

ご協力いただければ幸いです。

+0

これらは常に1文字ですか?文字列に貼り付けたり、正規表現や単純な文字列を使って正しいインデックスを見つけたりする方が簡単かもしれないようです。 – MrFlick

+0

こんにちはMrFlick、はいこれらは常に1文字です。私はしかし、あなたの提案されたソリューションを実装する方法を理解していない... –

+0

また、この類似[ポスト]を見つけるかもしれない(http://stackoverflow.com/questions/33027611/how-to-index-a-vector-ベクトルシーケンス内シーケンス)が役立ちます。 –

答えて

0
d = data.frame(num=1:15, char=c('A', 'K', 'I', 'B', 'I', 'N', 'G', 'O', 'Z', 'Q', 'B', 'I', 'N', 'G', 'O')) 
w = "BINGO" 
N = nchar(w) 
char_str = paste(d$char, sep='', collapse='') 

idx = as.integer(gregexpr(w, char_str)[[1]]) 
idx = as.integer(sapply(idx, function(i)seq(i, length=N))) 
d[idx, ] 

    num char 
4 4 B 
5 5 I 
6 6 N 
7 7 G 
8 8 O 
11 11 B 
12 12 I 
13 13 N 
14 14 G 
15 15 O 
+0

私はあなたの例を理解していません。 'gregexpr()'関数でどのように行を選択できますか?あなたが小さな説明をするといいだろう。 –

+0

のように見えます。そこに順不同では機能しません。この 'd = data.frame(num = 1:15、char = c( 'A'、 'K'、 'I'、 'B'、 'N'、 'I'、 'G'、 'O '、' Z '、' Q '、' X '、' I '、' N '、' G '、' O '))' –

+0

OPには順序付きの一致が必要です。 – Fernando

3

1つのオプションは使用することですzoo::rollapply

library(zoo) 
bingo = c("B", "I", "N", "G", "O") # the pattern you want to check 

# use rollapply to check if the pattern exists in any window 
index = which(rollapply(df$char, length(bingo), function(x) all(x == bingo))) 

# extract the window from the table 
df[mapply(`:`, index, index + length(bingo) - 1),] 

# num char 
#4 4 B 
#5 5 I 
#6 6 N 
#7 7 G 
#8 8 O 
+0

ありがとう。それは私が必要としていたものでした! –

0

私は誰もループのように思いますが、これはベースで可能性である:私はあまりにも速く、初めてが、ベースを行ってきました

char <- c("A", "K", "I", "B", "I", "N", "G", "O", "Z", "Q") 
num <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
df <- data.frame(num, char) 

word <- "BINGO" 
index <- NULL 
for(z in 1:nrow(df)){ 
    if(substr(word, 1,1) == as.character(df[z,2])){ 
    index <- c(index, z) 
    word <- substr(word, 2, nchar(word))  
    } 
} 

df[index,] 
0

あなたが与えた例では、私はこれがうまくいくと思います:

filter(df[which(df$char == "B"):dim(df)[1],], char %in% c("B","I","N","G","O")) 
+0

あなたの解決策でこのエラーメッセージが表示されました: 'フィルタのエラー(df [(df $ char ==" B "):dim(df)[1]、]、%cのchar% 'filter'は時系列より長く続きます。 –

1

ここでは、再帰関数を使用する解決策があります.BINGOの文字は連続する必要はありませんが、順番に並べる必要があります。

df <- data.frame(num=1:10,char=c("A","K","I","B","I","N","G","O","Z","Q"),stringsAsFactors = FALSE) 

word<-"BINGO" 

chars<-strsplit(word,"")[[1]] 

findword <- function(chars,df,a=integer(0),m=0){ #a holds the result so far on recursion, m is the position to start searching 
    z <- m+match(chars[1],df$char[(m+1):nrow(df)]) #next match of next letter 
    if(!is.na(z)){  
    if(length(chars)==1){ 
     a <- c(z,a) 
    } else { 
     a <- c(z,Recall(chars[-1],df,a,max(m,z))) #Recall is function referring to itself recursively 
    } 
    return(a) #returns row index numbers of df 
    } else { 
    return(NA) 
    } 
} 

result <- df[findword(chars,df),] 
+0

私の解決方法よりも50%高速でエレガントです+1 –

+0

ありがとうございました。機能にis.na(z)その言葉が見つからなければ厄介なクラッシュ。上記の編集。 –

関連する問題