You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用dplyr按组过滤数据并保留空组?

解决按组过滤并保留空组的问题

我明白你想要的效果:筛选出value > 5的行,但每个site组都得保留,哪怕这个组里没有符合条件的行,就用NA填充对应字段。你之前用的filter(.preserve = TRUE)没达到预期,是因为这个参数的作用并不是保留空组——它只是保留分组变量的结构,还是会删掉没有满足条件行的组。

下面给你两种用dplyr实现的方法:

方法一:用group_modify逐组处理

这个方法可以直接对每个分组做自定义判断,有符合条件的行就返回筛选结果,没有就返回NA行:

library(dplyr)

# 先构造你的示例数据
year = c(1,2,3,1,2,3,1,2,3)
site = rep(c("a", "b", "d"), each = 3)
value = c(3,3,0,1,8,5,10,18,27)
df <- data.frame(year, site, value)

# 核心代码
df %>%
  group_by(site) %>%
  group_modify(~ {
    # 筛选当前组里符合条件的行
    filtered_rows <- .x %>% filter(value > 5)
    # 如果筛选后没有行,返回NA填充的行;否则返回筛选结果
    if (nrow(filtered_rows) == 0) {
      tibble(year = NA, value = NA)
    } else {
      filtered_rows
    }
  }) %>%
  ungroup() # 可选,不需要分组的话可以取消分组

运行后就能得到你想要的结果:

# A tibble: 5 × 3
  site   year value
  <chr> <dbl> <dbl>
1 a        NA    NA
2 b         2     8
3 d         1    10
4 d         2    18
5 d         3    27

方法二:用right_join补全空组

这个思路更简洁:先筛选出符合条件的行,再和所有site的列表做右连接,这样就能保留所有site,没有匹配的行自动用NA填充:

df %>%
  filter(value > 5) %>%
  # 右连接所有不重复的site
  right_join(df %>% distinct(site), by = "site") %>%
  # 按site排序,和你的期望输出一致
  arrange(site)

这个方法同样能得到完全符合要求的结果,适合喜欢简洁代码的场景。

为什么你之前的代码没用?

filter的.preserve = TRUE参数只是用来保留分组变量的元数据(比如因子类型的分组变量不会被转成字符),但它不会改变filter的核心逻辑——只要某个分组里没有任何行满足过滤条件,这个分组就会被移除。所以site=a的组就被过滤掉了,这和你想要的效果不符。

内容的提问来源于stack exchange,提问作者maycca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:07:43