【问题标题】:Partial animal string matching in RR中的部分动物字符串匹配
【发布时间】:2014-05-21 20:57:18
【问题描述】:

我有一个数据框,

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),但它没有解决这个问题中存在的多个名称扭曲。

【问题讨论】:

    标签: r string dataframe matching


    【解决方案1】:

    可能有比这更优雅的解决方案,但您可以使用 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"
    

    我假设您的意思是“鸟类”,而忽略了“斗牛犬”,因为它包含“狗”。

    您可能希望将 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
    

    【讨论】:

      【解决方案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. 因为它是一个循环,而不是重复的手动调用,所以向“正则表达式”对象添加更多行和类别不需要进一步修改代码。它会像现在一样运行。

      唯一的缺点 - 我认为这适用于您可能获得的大多数解决方案,如果某物匹配多个模式,则它匹配的列表中的最后一个模式将是它的“物种”标签。

      【讨论】:

      • 关于是否可以有多个匹配项的要点。 @Brocolli-Rob:如果您的数据集中可能出现这种情况,那么为每个物种设置一个 TRUE/FALSE 列可能是一种更好的方法。
      【解决方案3】:

      另一种方法是创建查找表并将按索引与grepmatch 组合匹配

      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)
      
      avian <- c("bird", "eagle", "sparrow")
      canine <- c("dog", "yorkie", "bulldog")
      feline <-  c("cat", "lion", "tiger", "panther")
      
      lu <- stack(tibble::lst(avian, canine, feline))
      lu2 <- stack(sapply(lu$values, grep, x = d$name, ignore.case = TRUE))
      lu2$ind <- as.character(lu$ind[match(as.character(lu2$ind), lu$values)])
      
      d$species <- d$name
      d$species[lu2$values] <- as.character(lu2$ind)
      
      d
      #>                  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
      

      reprex package (v2.0.1) 于 2021 年 11 月 13 日创建

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-20
        • 1970-01-01
        • 2014-08-07
        • 1970-01-01
        • 1970-01-01
        • 2016-10-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多