关于r:结合group_by、ifelse和filter

Combine group_by, ifelse and filter

我想结合 group_by、ifelse 并为下面的示例数据框过滤我的代码。我想要的是以下内容:1)按x分组。 2)检查结果是否> 1。如果为真,检查该组的结果> 1 == max(月)的月份。如果为 TRUE,则选择该组的所有行。所有其他行都应该被丢弃(所以在结果 <= 1 或 (month where result > 1 != max(month)) 的情况下。所以在我的示例数据框中,B 的所有行都应该保留,A 的所有行都应该保留丢弃。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   x month result
1  A     1    0.5
2  A     2    0.6
3  A     3    1.2
4  A     4    1.1
5  A     5    0.9
6  B     1    0.3
7  B     2    0.4
8  B     3    0.5
9  B     4    0.9
10 B     5    1.2


dat <- data.frame(x = c("A","A","A","A","A","B","B","B","B","B"),
                  month = c(1,2,3,4,5,1,2,3,4,5),
                  result = c(.5,.6,1.2,1.1,.9,.3,.4,.5,.9,1.2))

使用 data.table

1
2
3
4
5
6
7
8
library(data.table)
setDT(dat)[,  .SD[result[which.max(month)] > 1], x]
#   x month result
#1: B     1    0.3
#2: B     2    0.4
#3: B     3    0.5
#4: B     4    0.9
#5: B     5    1.2

或与 dplyr

1
2
3
4
5
6
7
8
9
10
11
12
13
library(dplyr)
dat %>%
   group_by(x) %>%
   filter(result[which.max(month)] > 1)
# A tibble: 5 x 3
# Groups:   x [1]
#  x     month result
#  <fct> <dbl>  <dbl>
#1 B         1    0.3
#2 B         2    0.4
#3 B         3    0.5
#4 B         4    0.9
#5 B         5    1.2

如果您想留在 tidyverse 中而不是冒险进行基础选择,我们也可以轻松到达那里,只需使用 any 来检查组中是否有任何符合您的条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
dat %>%
  group_by(x) %>%
  filter(any(result > 1 & month == max(month)))

# A tibble: 5 x 3
# Groups:   x [1]
  x     month result
  <fct> <dbl>  <dbl>
1 B         1    0.3
2 B         2    0.4
3 B         3    0.5
4 B         4    0.9
5 B         5    1.2

另外,有时我会创建一个"keep"变量来检查我是否得到了正确的变量,或者是为了让多年后查看我的代码的人更容易阅读代码:

1
2
3
4
dat %>%
   group_by(x) %>%
   mutate(keep = (result > 1 & month == max(month))) %>%
   filter(any(keep))


这是一个带有 base R 的解决方案(没有 group_byfilter)

1
2
res <- Reduce(rbind,lapply(split(dat,dat$x), function(v) {
               if (v$result[which.max(v$month)]>1) v else NULL}))

这样

1
2
3
4
5
6
7
> res
   x month result
6  B     1    0.3
7  B     2    0.4
8  B     3    0.5
9  B     4    0.9
10 B     5    1.2