web-dev-qa-db-ja.com

複数のパターンを持つ文字ベクトルを使用したgrep

grepを使用して、文字列のベクトルが別のベクトルに存在するかどうかをテストし、存在する値(一致するパターン)を出力しようとしています。

次のようなデータフレームがあります。

FirstName Letter   
Alex      A1
Alex      A6
Alex      A7
Bob       A1
Chris     A9
Chris     A6

「Letter」列にある文字列パターンのベクトルがあります。例:c("A1", "A9", "A6")

パターンベクトルの文字列のいずれかが「レター」列に存在するかどうかを確認したいと思います。もしそうなら、一意の値の出力が欲しいです。

問題は、複数のパターンでgrepを使用する方法がわからないことです。私は試した:

matches <- unique (
    grep("A1| A9 | A6", myfile$Letter, value=TRUE, fixed=TRUE)
)

しかし、それは私に0の一致を与えますが、これは真実ではありません、何か提案はありますか?

115
user971102

fixed==TRUEを含めないという@Marekのコメントに加えて、正規表現にスペースを含める必要もありません。 "A1|A9|A6"である必要があります。

また、多くのパターンがあることにも言及しています。それらがベクトル内にあると仮定します

toMatch <- c("A1", "A9", "A6")

次に、これから直接正規表現を作成できます。

matches <- unique (grep(paste(toMatch,collapse="|"), 
                        myfile$Letter, value=TRUE))
243
Brian Diggs

良い答えですが、dplyrのfilter()を忘れないでください:

patterns <- c("A1", "A9", "A6")
>your_df
  FirstName Letter
1      Alex     A1
2      Alex     A6
3      Alex     A7
4       Bob     A1
5     Chris     A9
6     Chris     A6

result <- filter(your_df, grepl(paste(patterns, collapse="|"), Letter))

>result
  FirstName Letter
1      Alex     A1
2      Alex     A6
3       Bob     A1
4     Chris     A9
5     Chris     A6
25
Adamm

Brian Diggの投稿に基づいて、リストのフィルタリングに役立つ2つの関数を次に示します。

#Returns all items in a list that are not contained in toMatch
#toMatch can be a single item or a list of items
exclude <- function (theList, toMatch){
  return(setdiff(theList,include(theList,toMatch)))
}

#Returns all items in a list that ARE contained in toMatch
#toMatch can be a single item or a list of items
include <- function (theList, toMatch){
  matches <- unique (grep(paste(toMatch,collapse="|"), 
                          theList, value=TRUE))
  return(matches)
}
8
Austin D

この答えがすでに現れているかどうかわからない...

質問の特定のパターンについては、単一のgrep()呼び出しでそれを行うことができます。

grep("A[169]", myfile$Letter)
5
Assaf

Brian Diggsの回答に追加します。

greplを使用する別の方法では、すべての値を含むデータフレームが返されます。

toMatch <- myfile$Letter

matches <- myfile[grepl(paste(toMatch, collapse="|"), myfile$Letter), ]

matches

Letter Firstname
1     A1      Alex 
2     A6      Alex 
4     A1       Bob 
5     A9     Chris 
6     A6     Chris

たぶん少しクリーナー...多分?

4
StatGenGeek

match()またはcharmatch()関数を試しましたか?

使用例:

match(c("A1", "A9", "A6"), myfile$Letter)
4
user3877096

これは動作するはずです:

grep(pattern = 'A1|A9|A6', x = myfile$Letter)

またはさらに簡単に:

myfile$Letter %like% 'A1|A9|A6'
3
BOC

スペースを奪います。だから:

matches <- unique(grep("A1|A9|A6", myfile$Letter, value=TRUE, fixed=TRUE))
2
user9325029

sapplyを使用する

 patterns <- c("A1", "A9", "A6")
         df <- data.frame(name=c("A","Ale","Al","Lex","x"),Letters=c("A1","A2","A9","A1","A9"))



   name Letters
1    A      A1
2  Ale      A2
3   Al      A9
4  Lex      A1
5    x      A9


 df[unlist(sapply(patterns, grep, df$Letters, USE.NAMES = F)), ]
  name Letters
1    A      A1
4  Lex      A1
3   Al      A9
5    x      A9
1
dondapati