web-dev-qa-db-fra.com

grepl dans R pour trouver des correspondances avec une liste de chaînes de caractères

Est-il possible d'utiliser un argument grepl pour faire référence à une liste de valeurs, peut-être en utilisant l'opérateur% in%? Je veux prendre les données ci-dessous et si le nom de l'animal contient "chien" ou "chat", je veux retourner une certaine valeur, disons "garder"; s'il n'a pas "chien" ou "chat", je veux retourner "défausser".

data <- data.frame(animal = sample(c("cat","dog","bird", 'doggy','kittycat'), 50, replace = T))

Maintenant, si je devais simplement le faire en faisant correspondre strictement les valeurs, disons, "chat" et "chien", je pourrais utiliser l'approche suivante:

matches <- c("cat","dog")

data$keep <- ifelse(data$animal %in% matches, "Keep", "Discard")

Mais l'utilisation de grep ou grepl ne fait référence qu'au premier argument de la liste:

data$keep <- ifelse(grepl(matches, data$animal), "Keep","Discard")

retour

Warning message:
In grepl(matches, data$animal) :
  argument 'pattern' has length > 1 and only the first element will be used

Remarque, j'ai vu ce fil dans ma recherche, mais cela ne semble pas fonctionner: grep en utilisant un vecteur de caractères avec plusieurs motifs

13
Marc Tulla

Vous pouvez utiliser un "ou" (|) dans l'expression régulière de grepl.

ifelse(grepl("dog|cat", data$animal), "keep", "discard")
# [1] "keep"    "keep"    "discard" "keep"    "keep"    "keep"    "keep"    "discard"
# [9] "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "discard" "keep"   
#[17] "discard" "keep"    "keep"    "discard" "keep"    "keep"    "discard" "keep"   
#[25] "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"   
#[33] "keep"    "discard" "keep"    "discard" "keep"    "discard" "keep"    "keep"   
#[41] "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"    "keep"   
#[49] "keep"    "discard"

L'expression régulière dog|cat indique au moteur d'expression régulière de rechercher "dog" ou "cat", et renvoie les correspondances pour les deux.

21
Rich Scriven

Je ne sais pas ce que vous avez essayé, mais cela semble fonctionner:

data$keep <- ifelse(grepl(paste(matches, collapse = "|"), data$animal), "Keep","Discard")

Semblable à la réponse à laquelle vous avez lié.

L'astuce consiste à utiliser la pâte:

paste(matches, collapse = "|")
#[1] "cat|dog"

Donc, il crée une expression régulière avec l'un ou l'autre chien OR chat et fonctionnerait également avec une longue liste de modèles sans les taper chacun.

Éditer:

Si vous effectuez cette opération pour sous-définir ultérieurement data.frame en fonction des entrées "Conserver" et "Supprimer", vous pouvez le faire plus directement en utilisant:

data[grepl(paste(matches, collapse = "|"), data$animal),]

De cette façon, les résultats de grepl qui sont VRAI ou FAUX sont utilisés pour le sous-ensemble.

14
docendo discimus

Essayez d'éviter ifelse autant que possible. Cela, par exemple, fonctionne bien

c("Discard", "Keep")[grepl("(dog|cat)", data$animal) + 1]

Pour un 123 graines que vous obtiendrez

##  [1] "Keep"    "Keep"    "Discard" "Keep"    "Keep"    "Keep"    "Discard" "Keep"   
##  [9] "Discard" "Discard" "Keep"    "Discard" "Keep"    "Discard" "Keep"    "Keep"   
## [17] "Keep"    "Keep"    "Keep"    "Keep"    "Keep"    "Keep"    "Keep"    "Keep"   
## [25] "Keep"    "Keep"    "Discard" "Discard" "Keep"    "Keep"    "Keep"    "Keep"   
## [33] "Keep"    "Keep"    "Keep"    "Discard" "Keep"    "Keep"    "Keep"    "Keep"   
## [41] "Keep"    "Discard" "Discard" "Keep"    "Keep"    "Keep"    "Keep"    "Discard"
## [49] "Keep"    "Keep"   
13
David Arenburg