web-dev-qa-db-fra.com

grep en utilisant un vecteur de caractère avec plusieurs motifs

J'essaie d'utiliser grep pour vérifier si un vecteur de chaînes est présent dans un autre vecteur ou non, et pour afficher les valeurs présentes (les modèles correspondants).

J'ai un cadre de données comme ceci:

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

J'ai un vecteur de motifs de chaînes à trouver dans les colonnes "Lettre", par exemple: c("A1", "A9", "A6").

Je voudrais vérifier si l’une quelconque des chaînes du vecteur de motif est présente dans la colonne "Lettre". S'ils le sont, je voudrais la sortie de valeurs uniques.

Le problème est que je ne sais pas comment utiliser grep avec plusieurs modèles. J'ai essayé:

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

Mais ça me donne 0 matches ce qui n’est pas vrai, des suggestions?

120
user971102

Outre le commentaire de @ Marek sur le fait de ne pas inclure fixed==TRUE, vous devez également ne pas avoir les espaces dans votre expression régulière. Ce devrait être "A1|A9|A6".

Vous mentionnez également qu'il y a beaucoup de modèles. En supposant qu'ils sont dans un vecteur

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

Ensuite, vous pouvez créer votre expression régulière directement à partir de cela.

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

Bonnes réponses, mais n'oubliez pas de filter() de 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
26
Adamm

D'après le message de Brian Digg, il existe deux fonctions utiles pour filtrer les listes:

#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

Pas sûr que cette réponse soit déjà apparue ...

Pour le motif particulier dans la question, vous pouvez simplement le faire avec un seul appel grep(),

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

Pour ajouter à Brian Diggs répondre.

autrement, utiliser grepl renverra un bloc de données contenant toutes vos valeurs.

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

Peut-être un peu plus propre ... peut-être?

4
StatGenGeek

Avez-vous essayé les fonctions match() ou charmatch()?

Exemple d'utilisation:

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

Cela devrait fonctionner:

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

Ou encore plus simplement:

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

Enlevez les espaces. Alors faites:

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

Utilisation de la 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