여러 패턴의 문자형 벡터를 사용하여 grep


132

I를 사용하는 것을 시도하고 grep있는 (패턴 매칭)되는 값을 문자열 벡터가 다른 벡터 아닌지에 존재하는지 여부를 검사하고, 출력한다.

다음과 같은 데이터 프레임이 있습니다.

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

"Letter"열에서 찾을 수있는 문자열 패턴의 벡터가 있습니다 (예 :) c("A1", "A9", "A6").

패턴 벡터의 문자열이 "Letter"열에 있는지 확인하고 싶습니다. 그렇다면 고유 값의 출력을 원합니다.

문제는 grep여러 패턴 으로 사용하는 방법을 모른다는 것 입니다. 나는 시도했다 :

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

그러나 그것은 사실이 아닌 0 개의 일치 항목을 제공합니다.


3
fixed=TRUE패턴이 진정한 정규 표현식 이기 때문에 사용할 수 없습니다 .
Marek

6
사용 match하거나 %in%또는 심지어 것은 ==입니다 정확히 일치를 비교하는 올바른 방법. 정규식은 이러한 작업에 매우 위험하며 예기치 않은 결과를 초래할 수 있습니다.
David Arenburg

답변:


269

를 포함하지 않는 것에 대한 @Marek의 의견 외에도 fixed==TRUE정규 표현식에 공백이 없어도됩니다. 이어야합니다 "A1|A9|A6".

또한 많은 패턴이 있다고 언급합니다. 그들이 벡터에 있다고 가정

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

그런 다음 pasteand를 사용하여 정규식을 직접 만들 수 있습니다 collapse = "|".

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

문자열 목록에 정규 표현식 연산자가 구두점으로 포함되어 있으면이 작업을 수행 할 수 있습니까?
user124123

@ user1987097 다른 정규 표현식 연산자를 사용하거나 사용하지 않고 동일한 방식으로 작동해야합니다. 이 기능이 작동하지 않는 구체적인 예가 있습니까?
Brian Diggs

@ user1987097은 점 또는 괄호 앞에 2 개의 백 슬래시를 사용합니다. 첫 번째 백 슬래시는 연산자를 비활성화하는 데 필요한 두 번째 백 슬래시를 해석하는 이스케이프 문자입니다.
mbh86

3
정확한 일치를 위해 정규 표현식을 사용하면 나에게 위험한 것처럼 보이며 예기치 않은 결과가 발생할 수 있습니다. 왜 안돼 toMatch %in% myfile$Letter?
David Arenburg

@ user4050 특별한 이유가 없습니다. 문제의 버전에는 그 내용이 있었으며 필요한지 여부에 대해 생각하지 않고 방금 전달했을 것입니다.
브라이언 딕스

34

좋은 답변이지만 filter()dplyr을 잊지 마십시오.

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

3
내가 생각 grepl- 우리가 grepl 분리에 대한 우호적 인을 사용하여 하나와 조합 할 수 있도록, 3 개 패턴을 (길이 3의 벡터)을 가지고 한 번에 하나의 패턴 작품 (우리는 길이가 1 인 벡터 필요) |, 기타와 행운을 시험해보십시오 :)
Adamm

3
아, 이제 알겠다 따라서 A1과 같은 것을 출력하는 압축 방법 | A2 그래서 모든 조건을 원한다면 붕괴는 & 기호로 표시됩니다. 감사합니다.
Ahdee

1
안녕하세요, )|(패턴을 분리 하는 데 사용 하면 더 강력해질 수 있습니다 paste0("(", paste(patterns, collapse=")|("),")"). 불행히도 그것은 또한 덜 덜 우아해진다. 이로 인해 pattern이 발생 (A1)|(A9)|(A6)합니다.
fabern

14

이것은 작동해야합니다 :

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

또는 더 간단하게 :

library(data.table)
myfile$Letter %like% 'A1|A9|A6'

11
%like%기본 R에 없으므로 패키지를 사용하는 데 필요한 패키지를 언급해야합니다.
Gregor Thomas

1
이 답변을 보는 다른 사람들에게는 패키지의 %like%일부입니다 data.table. 또한 비슷한에가 data.table있습니다 like(...), %ilike%그리고 %flike%.
steveb

8

Brian Digg의 게시물을 기반으로 목록을 필터링하는 데 유용한 두 가지 기능이 있습니다.

#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)
}

5

match()또는 charmatch()기능 을 사용해 보셨습니까 ?

사용 예 :

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

1
주목해야 할 것은 match패턴을 사용하지 않고 정확하게 일치 할 것으로 예상한다는 것입니다.
steveb

5

이 답변이 이미 있는지 확실하지 않습니다 ...

질문의 특정 패턴에 대해서는 한 번의 grep()호출로 수행 할 수 있습니다 .

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

4

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

좀 더 깨끗 할까 ... 어쩌면?


2

공간을 빼앗아 그렇습니다 :

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

1

사용하여 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

작은 스크립트를 작성하고 Grep을 사용하여 여러 번 검색하는 것이 좋습니다. 여러 패턴을 검색 할 수있는 방법을 찾지 못했고 나를 믿었습니다.

다음과 같이 문자열이 포함 된 쉘 파일 :

 #!/bin/bash 
 grep *A6* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
 grep *A7* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
 grep *A8* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";

그런 다음 myshell.sh를 입력하여 실행하십시오.

명령 행에서 문자열을 전달하려면 쉘 인수를 사용하여 다음과 같이하십시오 : bash 표기법 btw :

 #!/bin/bash 
 $stingtomatch = "${1}";
 grep *A6* "${stingtomatch}";
 grep *A7* "${stingtomatch}";
 grep *A8* "${stingtomatch}";

기타 등등.

일치시킬 패턴이 많으면 for 루프에 넣을 수 있습니다.


ChrisBean 감사합니다. 실제로 패턴은 많으므로 파일을 사용하는 것이 좋습니다. 나는 BASH를 처음 사용하지만 아마도 이런 식으로 작동해야합니다 ... 'pattern.txt'에서 나에게 #! / bin / bash # echo $ ij = 'grep -c "$ {i}"myfile.txt'echo $ j [$ j -eq o]이면 echo $ i >> matches.txt fi done
user971102

작동하지 않습니다 ... 오류 메시지는 '[grep : command not found'입니다. / bin 폴더에 grep이 있고 / bin이 $ PATH에 있습니다… 어떤 일이 일어나고 있는지 확실하지 않습니다… 도와 주실 수 있습니까?
user971102
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.