繁体   English   中英

filter() 但保留没有值的组

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM