如何按ID筛选DataFrame行:保留首个yesno=1记录或NA行
用dplyr实现ID分组筛选需求
示例数据构造
先还原你的输入数据(方便测试验证):
library(dplyr) df <- tibble( ID = c(1,1,1,1,1,2,3,3,3), yesno = c(0,0,0,1,1,0,0,0,1), date1 = c(NA, NA, NA, "2021-01-02", "2022-11-02", NA, NA, NA, "2022-03-04"), value1 = c(NA, NA, NA, 667, 123, NA, NA, NA, 111) )
解决方案一:排序后取首行(简洁版)
核心思路是通过排序让目标行落在每个分组的第一位,直接提取即可:
# 先将date1转为日期类型(保证日期排序逻辑正确) result <- df %>% mutate(date1 = as.Date(date1)) %>% group_by(ID) %>% # 排序规则:yesno=1优先(降序),同yesno下取最早的date1(升序) arrange(desc(yesno), date1) %>% # 提取每组第一行 slice(1) %>% ungroup()
输出结果:
# A tibble: 3 × 4 ID yesno date1 value1 <dbl> <dbl> <date> <dbl> 1 1 1 2021-01-02 667 2 2 0 NA NA 3 3 1 2022-03-04 111
解决方案二:拆分处理后合并(逻辑直观版)
如果觉得排序逻辑不够直观,可以拆分为两步处理后合并:
- 提取所有存在yesno=1的ID,保留其中date1最早的行
- 提取只有yesno=0的ID,保留任意一行(所有行都是NA,无差异)
- 合并结果并按ID排序
代码实现:
# 处理有yesno=1的ID df_yes1 <- df %>% mutate(date1 = as.Date(date1)) %>% filter(yesno == 1) %>% group_by(ID) %>% slice_min(date1, n = 1) %>% ungroup() # 处理只有yesno=0的ID df_yes0 <- df %>% group_by(ID) %>% filter(all(yesno == 0)) %>% slice(1) %>% ungroup() # 合并并排序 result <- bind_rows(df_yes1, df_yes0) %>% arrange(ID)
两种方法都能得到你需要的结果,可根据自身习惯选择。
内容的提问来源于stack exchange,提问作者Estelle
相关产品推荐
相关产品推荐

