【问题标题】:Filter multiple values on a string column in dplyr在 dplyr 中过滤字符串列上的多个值
【发布时间】:2014-10-28 03:21:45
【问题描述】:

我有一个data.frame,其中一列中有字符数据。 我想从同一列中过滤data.frame 中的多个选项。有没有一种我想念的简单方法来做到这一点?

示例: data.frame 姓名 = dat

days      name
88        Lynn
11          Tom
2           Chris
5           Lisa
22        Kyla
1          Tom
222      Lynn
2         Lynn

例如,我想过滤掉 Tom 和 Lynn。
当我这样做时:

target <- c("Tom", "Lynn")
filt <- filter(dat, name == target)

我收到此错误:

longer object length is not a multiple of shorter object length

【问题讨论】:

    标签: r dplyr string-matching multiple-conditions


    【解决方案1】:

    你需要%in% 而不是==:

    library(dplyr)
    target <- c("Tom", "Lynn")
    filter(dat, name %in% target)  # equivalently, dat %>% filter(name %in% target)
    

    生产

      days name
    1   88 Lynn
    2   11  Tom
    3    1  Tom
    4  222 Lynn
    5    2 Lynn
    

    要了解原因,请考虑这里发生的情况:

    dat$name == target
    # [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE
    

    基本上,我们将两个长度的target 向量循环四次以匹配dat$name 的长度。换句话说,我们正在做:

     Lynn == Tom
      Tom == Lynn
    Chris == Tom
     Lisa == Lynn
     ... continue repeating Tom and Lynn until end of data frame
    

    在这种情况下,我们没有收到错误,因为我怀疑您的数据框实际上有不同数量的不允许回收的行,但您提供的示例确实有(8 行)。如果样本有奇数行,我会得到和你一样的错误。但即使回收工作,这显然不是你想要的。基本上,声明dat$name == target 相当于说:

    为每个等于“Tom”的奇数值或每个等于“Lynn”的偶数值返回TRUE。

    碰巧您的示例数据框中的最后一个值是偶数并且等于“Lynn”,因此是上面的TRUE。

    相比之下,dat$name %in% target 说:

    对于dat$name 中的每个值,检查它是否存在于target。

    非常不同。结果如下:

    [1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE
    

    注意你的问题与dplyr无关,只是==的误用。

    【讨论】:

    • 感谢布罗迪的解释!非常感谢这一点,临床医生试图找出 R!
    • @BrodieG 你能用模式而不是完整的字符串来制作目标吗?
    • 不适用于%in%,但您可以使用grepl("T[oi]m|lynne?", name) 并使用您想要的任何模式。
    【解决方案2】:

    这可以使用 CRAN 中提供的 dplyr 包来实现。实现这一点的简单方法:

    1. 安装dplyr 包。
    2. 运行以下代码
    library(dplyr) 
    
    df<- select(filter(dat,name=='tom'| name=='Lynn'), c('days','name))
    
    

    解释:

    所以,一旦我们下载了 dplyr,我们就可以使用这个包中的两个不同的函数来创建一个新的数据框:

    filter:第一个参数是数据框;第二个参数是我们希望它子集化的条件。结果是整个数据框只有我们想要的行。 select:第一个参数是数据框;第二个参数是我们想要从中选择的列的名称。我们不必使用 names() 函数,甚至不必使用引号。我们只是将列名作为对象列出。

    【讨论】:

      【解决方案3】:

      使用base 包:

      df <- data.frame(days = c(88, 11, 2, 5, 22, 1, 222, 2), name = c("Lynn", "Tom", "Chris", "Lisa", "Kyla", "Tom", "Lynn", "Lynn"))
      
      # Three lines
      target <- c("Tom", "Lynn")
      index <- df$name %in% target
      df[index, ]
      
      # One line
      df[df$name %in% c("Tom", "Lynn"), ] 
      

      输出:

        days name
      1   88 Lynn
      2   11  Tom
      6    1  Tom
      7  222 Lynn
      8    2 Lynn
      

      使用sqldf:

      library(sqldf)
      # Two alternatives:
      sqldf('SELECT *
            FROM df 
            WHERE name = "Tom" OR name = "Lynn"')
      sqldf('SELECT *
            FROM df 
            WHERE name IN ("Tom", "Lynn")')
      

      【讨论】:

        【解决方案4】:
         by_type_year_tag_filtered <- by_type_year_tag %>%
              dplyr:: filter(tag_name %in% c("dplyr", "ggplot2"))
        

        【讨论】:

        • 虽然此代码可能提供问题的解决方案,但强烈建议您提供有关此代码为何和/或如何回答问题的附加上下文。从长远来看,只有代码的答案通常会变得毫无用处,因为未来遇到类似问题的观众无法理解解决方案背后的原因。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-15
        • 1970-01-01
        • 1970-01-01
        • 2018-02-19
        • 2021-12-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多