J'ai une trame de données,
d<-data.frame(name=c("brown cat", "blue cat", "big lion", "tall tiger",
"black panther", "short cat", "red bird",
"short bird stuffed", "big eagle", "bad sparrow",
"dog fish", "head dog", "brown yorkie",
"lab short bulldog"), label=1:14)
Je voudrais rechercher la colonne name
et si les mots "chat", "lion", "tigre" et "panthère" apparaissent, je veux affecter la chaîne de caractères feline
à une nouvelle colonne et la ligne correspondante species
.
Si les mots "bird", "eagle", and "sparrow"
apparaît, je veux affecter la chaîne de caractères avian
à une nouvelle colonne et à la ligne correspondante species
.
Si les mots "chien", "yorkie" et "bulldog" apparaissent, je veux affecter la chaîne de caractères canine
à une nouvelle colonne et la ligne correspondante species
.
Idéalement, je stockerais cela dans une liste ou quelque chose de similaire que je peux conserver au début du script, car comme de nouvelles variantes de l'espèce apparaissent dans la catégorie de nom, ce serait bien d'avoir un accès facile pour mettre à jour ce qui est qualifié en tant que feline
, avian
et canine
.
Cette question est presque résolue ici (Comment créer une nouvelle colonne dans un dataframe basé sur une chaîne partielle correspondant à une autre colonne dans R), mais il ne résout pas la torsion de plusieurs noms présente dans ce problème.
Il peut y avoir une solution plus élégante que cela, mais vous pouvez utiliser grep
avec |
pour spécifier des correspondances alternatives.
d[grep("cat|lion|tiger|panther", d$name), "species"] <- "feline"
d[grep("bird|eagle|sparrow", d$name), "species"] <- "avian"
d[grep("dog|yorkie", d$name), "species"] <- "canine"
J'ai supposé que vous vouliez dire "aviaire" et j'ai omis "bouledogue" car il contient "chien".
Vous voudrez peut-être ajouter ignore.case = TRUE
au grep.
production:
# name label species
#1 brown cat 1 feline
#2 blue cat 2 feline
#3 big lion 3 feline
#4 tall tiger 4 feline
#5 black panther 5 feline
#6 short cat 6 feline
#7 red bird 7 avian
#8 short bird stuffed 8 avian
#9 big eagle 9 avian
#10 bad sparrow 10 avian
#11 dog fish 11 canine
#12 head dog 12 canine
#13 brown yorkie 13 canine
#14 lab short bulldog 14 canine
Une façon élégante de le faire (je dis élégant-parce que, même si c'est la façon la plus élégante que je connaisse, ce n'est pas génial), c'est quelque chose comme:
#Define the regexes at the beginning of the code
regexes <- list(c("(cat|lion|tiger|panther)","feline"),
c("(bird|eagle|sparrow)","avian"),
c("(dog|yorkie|bulldog)","canine"))
....
#Create a vector, the same length as the df
output_vector <- character(nrow(d))
#For each regex..
for(i in seq_along(regexes)){
#Grep through d$name, and when you find matches, insert the relevant 'tag' into
#The output vector
output_vector[grepl(x = d$name, pattern = regexes[[i]][1])] <- regexes[[i]][2]
}
#Insert that now-filled output vector into the dataframe
d$species <- output_vector
Les avantages de cette méthode sont multiples
Le seul inconvénient - et cela s'applique à, je pense, à la plupart des solutions que vous obtiendrez probablement, est que si quelque chose correspond à plusieurs modèles, le dernier modèle de la liste auquel il correspond sera sa balise `` espèce ''.