如何在R中简洁实现DataFrame组内状态过滤(含全inactive组例外)?
问题描述
假设我有如下DataFrame:
dat <- data.frame(account = c(1, 2, 3, 4, 5, 6, 7, 8, 9), group = c("a", "a", "b", "b", "c", "c", "c", "d", "d"), status = c("active", "inactive", "inactive", "inactive", "active", "open", "inactive", "active", "active"))
我需要对数据做过滤,要求每个组(a、b、c等)至少留一个账户。过滤规则是:只保留状态为active或open的账户,除非这个组的所有账户状态都是inactive,这种情况至少保留一条。
我现在用多步代码实现了需求(如下),但想知道有没有更简洁的单步实现方式?
active_open <- dat %>% group_by(group) %>% filter(status == "active" | status == "open") %>% ungroup() inactive <- dat %>% group_by(group) %>% filter(n_distinct(status) == 1 & status == "inactive") %>% slice_head(n = 1) %>% ungroup() dat_clean <- bind_rows(active_open, inactive)
简洁实现方案
可以用dplyr的分组过滤逻辑,一次分组操作就能完成所有判断,不用拆分后再合并:
dat_clean <- dat %>% group_by(group) %>% filter( # 保留状态为active或open的记录 status %in% c("active", "open") | # 组内全是inactive的话,只留第一条 (all(status == "inactive") & row_number() == 1) ) %>% ungroup()
逻辑说明
- 按组分组后,先筛出状态是
active或open的记录,这些是我们优先要保留的 - 对于那些组里没有active/open记录的情况(也就是全是inactive),我们只保留组内的第一条记录,保证每个组至少有一条数据
结果验证
运行上面的代码后,得到的dat_clean和你原来多步实现的结果完全一致:
# A tibble: 6 × 3 account group status <dbl> <chr> <chr> 1 1 a active 2 3 b inactive 3 5 c active 4 6 c open 5 8 d active 6 9 d active
内容的提问来源于stack exchange,提问作者setty
相关产品推荐
相关产品推荐

