【问题标题】:filtering rows with same condition on more than one column在多列上过滤具有相同条件的行
【发布时间】:2017-08-25 07:48:18
【问题描述】:

我想在不同的列中使用相同的条件来选择行。

set.seed(123)
df <- data.frame(col.x = sample(LETTERS[1:10], 20, replace = TRUE), 
                 col.y = sample(LETTERS[1:10], 20, replace = TRUE), 
                 val = rnorm(20))

我只需要在ValsToRetain 两列col.xcol.y 中包含值。

ValsToRetain <- c('A','D', 'F','H','J')

我已经尝试了这两种方法,它们给出了相同的预期输出。

df %>% filter(col.x %in% ValsToRetain) %>% filter(col.y %in% ValsToRetain)
df %>% filter(col.x %in% ValsToRetain & col.y %in% ValsToRetain)
#   col.x col.y        val
# 1     A     H -1.6866933
# 2     F     F  0.8377870
# 3     J     J  0.4264642
# 4     F     H  0.8781335
# 5     D     D -0.3059627

但是,还有其他优雅的方法可以做到这一点吗?

例如;比如在这些列中计算rowSums 以检查它是否有nas。由于有多个值,我无法得到类似rowSums(df[,1:2] == 'A') 的想法。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我们可以使用filter_atall_vars

    df %>% 
      filter_at(vars(starts_with("col")), all_vars(. %in% ValsToRetain))
    #   col.x col.y        val
    #1     A     H -1.6866933
    #2     F     F  0.8377870
    #3     J     J  0.4264642
    #4     F     H  0.8781335
    #5     D     D -0.3059627
    

    【讨论】:

    • 谢谢,这绝对是一种优雅的方式。如果列名是xvaryvarvalvar,您是否看到其他方法?是filter_at(vars('xvar', 'yvar'), all_vars(. %in% ValsToRetain)) 吗?顺便说一句,您使用的是哪个版本的dplyr?我收到一个错误could not find function "filter_at"
    • 你可以取否定版本的 vars,即df %&gt;% filter_at(vars(-val), all_vars(. %in% ValsToRetain))
    【解决方案2】:

    这是使用Reducelapply 的基本R 方法。 lapply 在相关列中应用 %in%,返回逻辑向量列表。然后Reduce 使用&amp; 将这些向量组合成一个向量。

    df[Reduce("&", lapply(df[c("col.x", "col.y")], "%in%", ValsToRetain)),]
       col.x col.y        val
    6      A     H -1.6866933
    7      F     F  0.8377870
    11     J     J  0.4264642
    14     F     H  0.8781335
    19     D     D -0.3059627
    

    如果您有很多列进行比较,那么您可以使用grep 来选择它们,例如grep("^col", names(df)) 代替c("col.x", "col.y")

    【讨论】:

      【解决方案3】:

      您可以使用子集,它很短但与您的方法相同:

      filt <- subset(df,col.x %in% ValsToRetain & col.y %in% ValsToRetain)
      

      输出是:

       col.x col.y        val
           A     H -1.6866933
           F     F  0.8377870
           J     J  0.4264642
           F     H  0.8781335
           D     D -0.3059627
      

      【讨论】:

      • 这与 OP 的第二个选项完全相同 df %>% filter(col.x %in% ValsToRetain & col.y %in% ValsToRetain) - 你刚刚使用subset 而不是 filter
      • @Sotos 这正是我所说的“与你的方法相同”,所以我猜你不必投反对票
      • 好吧,我觉得在这里投反对票是合理的,因为 OP 寻求任何其他优雅的方式来做到这一点...我的意思是你可以用不同的东西更新至少给你的回答一些价值,我很乐意推翻我的投票。例如,类似于df %&gt;% mutate_at(vars(-val), funs((replace(., !. %in% ValsToRetain, NA)))) %&gt;% na.omit() 的东西应该这样做
      • 虽然和我说的一模一样,但是感谢baseR函数的提醒!
      猜你喜欢
      • 2022-01-19
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      相关资源
      最近更新 更多