R中的部分动物串匹配

时间:2014-04-08 22:19:00

标签: r string dataframe matching

我有一个数据框,

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)

我想搜索name列以及是否有单词 出现“cat”,“lion”,“tiger”和“panther”,我想将字符串feline分配给新列和相应的行species

如果出现"bird", "eagle", and "sparrow"字样,我想将字符串avian分配给新列和相应的行species

如果出现“dog”,“yorkie”和“bulldog”字样,我想将字符串canine分配给新列和相应的行species

理想情况下,我会将此存储在列表或类似的内容中,我可以将其保存在脚本的开头,因为当物种的新变种出现在名称类别中时,可以轻松访问更新符合felineaviancanine的条件。

这个问题几乎在这里得到解答( How to create new column in dataframe based on partial string matching other column in R ),但它没有解决此问题中存在的多重名称扭曲。

2 个答案:

答案 0 :(得分:26)

可能有一个比这更优雅的解决方案,但您可以使用grep|来指定替代匹配。

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"

我认为你的意思是#av; avian&#34;并且遗漏了#34;斗牛犬&#34;因为它包含&#34; dog&#34;。

您可能希望将ignore.case = TRUE添加到grep。

输出:

#                 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

答案 1 :(得分:2)

这是一种优雅的方式(我说优雅,因为,虽然它是我所知道的最优雅的方式,但并不是很好),如下所示:

#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

这种方法的优点是几倍

  1. 您只需要在整个过程中修改一次数据帧,这样可以提高循环的速度(数据框没有就地修改;修改数据框3次,你基本上是重新标记并重新创建它3次)。
  2. 通过预先指定向量的长度,因为我们知道它将会是什么,所以通过确保输出向量在创建之后永远不需要更多的内存来提高速度。
  3. 因为它是一个循环而不是重复的手动调用,所以在“正则表达式”中添加了更多行和类别。对象不需要进一步修改代码。它会像现在一样运行。
  4. 唯一的缺点 - 我认为,这适用于您可能获得的大多数解决方案,如果某些内容符合多种模式,则匹配的列表中的最后一个模式将是其物种&#39; #39;标签