【问题标题】:Dplyr filtering based on two variables基于两个变量的 Dplyr 过滤
【发布时间】:2023-06-27 20:34:02
【问题描述】:

我想使用dplyr 来确定数据框中的哪些观察满足以下条件:

  • 在每个Group 内,Var2 的组合总数为Var1 == good 大于Var1 == bad 的观察值的组合总数

这是玩具数据框:

library(dplyr)

set.seed(seed = 10)

df <- data.frame("Id" = 1:12,
                 "Group" = paste(sapply(toupper(letters[1:3]), rep, times = 4,simplify = T)),
                 "Var1" = sample(rep(c("good","bad"),times = 1000),size = 12),
                 "Var2" = sample(rep(1:10, times = 1000),size = 12))

print(df)

   Id Group Var1 Var2
1   1     A good    6
2   2     A  bad    9
3   3     A good   10
4   4     A good    7
5   5     B  bad    9
6   6     B  bad    1
7   7     B  bad    6
8   8     B good    6
9   9     C good    1
10 10     C  bad    8
11 11     C good    4
12 12     C  bad    2

到目前为止,我已经确定我应该使用group_by()summarise()filter() 的某种组合,但我似乎无法找到一个好的方法。到目前为止,这是我想出的:

keepers <- df %>% 
        group_by(Group, Var1) %>%
        summarise(Total = sum(Var2)) %>% 
        print()

Source: local data frame [6 x 3]
Groups: Group [?]

  Group  Var1 Total
  (chr) (chr) (int)
1     A   bad     9
2     A  good    23
3     B   bad    16
4     B  good     6
5     C   bad    10
6     C  good     5

我应该采取哪些后续步骤?最终分析应该返回“A”,因为它是唯一的Group,其中Total 对于good 观察值大于bad 观察值。

【问题讨论】:

  • 注意:第一次发帖!如果我错误地或笨拙地格式化了这个问题,请帮助我。欢迎提出建设性的批评。
  • 第一次问的问题非常巧妙,+1

标签: r dplyr tidyr spread


【解决方案1】:

使用spread而不是filter怎么样:

> library(tidyr)
> df %>% group_by(Group, Var1) %>%
+    summarise(Total = sum(Var2)) %>%
+    spread(Var1,Total) %>%
+    filter(good>bad)
Source: local data frame [1 x 3]

  Group bad good
1     A   9   23

【讨论】:

  • 这行得通!我的回答有误,但在我修复它之前,@fishtank 已经提供了正确的答案。
  • 这个解决方案正是我想要的! @fishtank 感谢您向我介绍spread 功能!
【解决方案2】:

data.table 的类似选项。我们将'data.frame'转换为'data.table'(setDT(df)),按'Group'、'Var1'分组,得到'Var2'的sum,从'long'重塑为'wide'和过滤“好”大于“坏”的行。

library(data.table)
dcast(setDT(df)[, sum(Var2) , by = .(Group, Var1)], 
               Group~Var1, value.var='V1')[good>bad]
#   Group bad good
#1:     A   9   23

【讨论】: