【问题标题】:Filter using a vector that has the column names使用具有列名的向量进行过滤
【发布时间】:2020-08-24 14:21:03
【问题描述】:

我已经搜索了不同的问题,但没有得到任何解决方案...抱歉,如果问题重复了。

我有这个 data.table 或数据框:

a <- rep(1:8)
b <- rep(c("Incorrect","Correct", "Correct", "Incorrect"), each = 1)
c <- rep(c("Correct", "Incorrect", "Correct", "Correct"), each = 1)
df <- data.table(a,b,c)

df

   a         b         c
1: 1 Incorrect   Correct
2: 2   Correct Incorrect
3: 3   Correct   Correct
4: 4 Incorrect   Correct
5: 5 Incorrect   Correct
6: 6   Correct Incorrect
7: 7   Correct   Correct
8: 8 Incorrect   Correct

为了过滤所有不正确的值,我将要过滤的所有名称变量/列保留在向量中。然后我按我需要的向量的长度复制粘贴(在这种情况下,我按 1 和 2 过滤)。

columns <- c("b","c")

df[get(columns[1])== "Incorrect" | get(columns[2])=="Incorrect",]

   a         b         c
1: 1 Incorrect   Correct
2: 2   Correct Incorrect
3: 4 Incorrect   Correct
4: 5 Incorrect   Correct
5: 6   Correct Incorrect
6: 8 Incorrect   Correct

有没有办法在不复制粘贴我要过滤的列向量的每个值的情况下做到这一点?我至少有 20 个变量名...我应该考虑另一种方法吗?

任何帮助将不胜感激。提前致谢!

【问题讨论】:

  • rep(1:8) 等于 1:8。
  • 根据给定的示例行,所有“正确”条目都需要删除,即保留至少有一个“不正确”条目的行
  • @desval 我的错误。

标签: r database dataframe data.table


【解决方案1】:

如果我没记错的话,如果所选列中的所有值都是“正确的”,您想删除一行。

columns <- c("b","c")
df[apply(df[,..columns], 1, function(x) any( x=="Incorrect")) ]

   a         b         c
1: 1 Incorrect   Correct
2: 2   Correct Incorrect
3: 4 Incorrect   Correct
4: 5 Incorrect   Correct
5: 6   Correct Incorrect
6: 8 Incorrect   Correct

如果dfdata.frame

df[apply(df[,columns], 1, function(x) any( x=="Incorrect")),]

【讨论】:

    【解决方案2】:
    ids <- df[, melt(df, id.vars = "a")
              ][, if (any(value == "Incorrect")) a, by = a]$V1
    df[a %in% ids]
    
    #    a         b         c
    # 1: 1 Incorrect   Correct
    # 2: 2   Correct Incorrect
    # 3: 4 Incorrect   Correct
    # 4: 5 Incorrect   Correct
    # 5: 6   Correct Incorrect
    # 6: 8 Incorrect   Correct
    

    【讨论】:

      【解决方案3】:

      我建议使用文本链连接所有条件并为过滤器评估它的方法:

      #Data
      a <- 1:8
      b <- rep(c("Incorrect","Correct", "Correct", "Incorrect"), each = 1)
      c <- rep(c("Correct", "Incorrect", "Correct", "Correct"), each = 1)
      df <- data.frame(a,b,c,stringsAsFactors = F)
      #Vars
      columns <- c("b","c")
      

      在这里,我们构建文本链:

      #Chain
      chain <- paste0('df$',columns,'=="Incorrect"')
      chain2 <- paste0(chain,collapse = '|')
      

      现在是过滤器:

      #Filter
      df[eval(parse(text=chain2)),]
      

      输出:

        a         b         c
      1 1 Incorrect   Correct
      2 2   Correct Incorrect
      4 4 Incorrect   Correct
      5 5 Incorrect   Correct
      6 6   Correct Incorrect
      8 8 Incorrect   Correct
      

      我没有 data.table 包,这就是我将数据创建为 data.frame 的原因,但该解决方案也适用于 data.table 对象。

      【讨论】:

        【解决方案4】:

        您可以考虑在dplyr 1.0.0 及更高版本中使用c_across() 的方法

        library(dplyr)
        df %>% 
          rowwise() %>% 
          filter(any(str_detect(c_across(c(b, c)), "Incorrect")))
        
        # Rowwise: 
        # a b         c        
        # <int> <chr>     <chr>    
        # 1     1 Incorrect Correct  
        # 2     2 Correct   Incorrect
        # 3     4 Incorrect Correct  
        # 4     5 Incorrect Correct  
        # 5     6 Correct   Incorrect
        # 6     8 Incorrect Correct  
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-08-25
          • 2018-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多