[英]group_by and keep all groups that does not not contain specific value and filter where there is value
[英]filter() but keep groups without value
我正在尝试压缩分组的 df,仅提取包含特定值的行,但该值并未反映在所有组中。 我想找到一种方法来提取具有该值的所有行,但还要为不包含该值的组创建 NA 或 0 行。
前任:
x1 <- c('1','1','1','1','1','2','2','2','2','2','3','3','3','3','3')
x2 <- c('a','b','c','d','e','b','c','d','e','f','a','b','d','e','f')
df <- data.frame(x1,x2)
df %>% group_by(x1) %>%
filter(x2 =="a")
这将返回:
x1 x2
<fct> <fct>
1 1 a
2 3 a
但我希望它返回:
x1 x2
<fct> <fct>
1 1 a
2 2 NA
3 3 a
显然,真正的代码要复杂得多,所以我正在寻找以可重现的方式保留这些空组的最佳方法。
PS - 我想留在 dplyr 以保持功能链中的流畅
谢谢!
一种dplyr
选项可能是:
df %>%
group_by(x1) %>%
slice(which.max(x2 == "a")) %>%
mutate(x2 = replace(x2, x2 != "a", NA_complex_))
x1 x2
<fct> <fct>
1 1 a
2 2 <NA>
3 3 a
如果每个组有多个目标值是相关的:
df %>%
group_by(x1) %>%
filter(x2 == "a") %>%
bind_rows(df %>%
group_by(x1) %>%
filter(all(x2 != "a")) %>%
slice(1) %>%
mutate(x2 = replace(x2, x2 != "a", NA_complex_)))
这是因为 Dplyr 的编写方式。 根据 Hadley Wickham(包创建者)的说法,要维护 NA 值,您应该明确声明您想要它们。 正如他在 github 上的这个问题中所说,你应该filter(a == x | is.na(a))
。 在您的情况下,您使用以下内容:
df %>% group_by(x1) %>%
filter(x2 =="a" | is.na(x2)
结果你会返回这个:
x1 x2
<fct> <fct>
1 1 a
2 2 NA
3 3 a
在此代码中,您要求 R 所有 x2 等于“a”的行以及 x2 为 NA 的所有行。
由于您没有仅指定 dplyr 解决方案,这是library(data.table)
的一个选项
setDT(df)
df[, .(x2 = x2[match('a', x2)]), x1]
# x1 x2
# 1: 1 a
# 2: 2 <NA>
# 3: 3 a
我们可以在filter
步骤之后使用complete
来获取缺失的组合。 默认情况下,所有其他列都将填充NA
(可以使用fill
参数将其设置为自定义值)
library(dplyr)
library(tidyr)
df %>%
filter(x2 == 'a') %>%
complete(x1 = unique(df$x1))
# A tibble: 3 x 2
# x1 x2
# <fct> <fct>
#1 1 a
#2 2 <NA>
#3 3 a
另一种选择是match
df %>%
group_by(x1) %>%
summarise(x2 = x2[match('a', x2)])
如果有很多列,则使用match
mutate
'x2',然后对第一行进行slice
df %>%
group_by(x1) %>%
mutate(x2 = x2[match('a', x2)]) %>%
slice(1)
使用如下所示的aggregate()
的基本R 解决方案怎么样?
dfout <- aggregate(x2~x1,df,function(v) ifelse("a" %in% v,"a",NA))
或者
dfout <- aggregate(x2~x1,df,function(v) v[match("a", v)])
以至于
> dfout
x1 x2
1 1 a
2 2 <NA>
3 3 a
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.