R语言分组聚合:如何保留其他列并获取起止日期极值?
按ID分组获取起止日期及关联列的实现方法
数据背景
假设存在如下R语言dataframe:
df <- data.frame(id = c(1,1,1,2,2,2,3,3,3,3), col1 = c("a","a", "b", "c", "d", "e", "f", "g", "h", "g"), start_day = c(NA,1,15, NA, 4, 22, 5, 11, 14, 18), end_day = c(NA,2, 15, NA, 6, 22, 6, 12, 16, 21))
输出结果为:
id col1 start_day end_day 1 1 a NA NA 2 1 a 1 2 3 1 b 15 15 4 2 c NA NA 5 2 d 4 6 6 2 e 22 22 7 3 f 5 6 8 3 g 11 12 9 3 h 14 16 10 3 g 18 21
需求说明
按唯一id分组,获取start_day列的最小值、end_day列的最大值,同时保留对应的关联列(如col1),最终得到包含col1_start(对应最小start_day的col1值)和col1_end(对应最大end_day的col1值)的结果。直接使用group_by()+summarise()会丢失col1列,无法满足需求。
解决方案
方法1:用dplyr的slice_min/slice_max拆分合并
分别提取每个组中start_day最小、end_day最大的行,再通过ID合并结果:
library(dplyr) # 提取每组最小start_day对应的行 min_start_df <- df %>% group_by(id) %>% slice_min(start_day, na_rm = TRUE, with_ties = FALSE) %>% select(id, col1_start = col1, min_start_day = start_day) # 提取每组最大end_day对应的行 max_end_df <- df %>% group_by(id) %>% slice_max(end_day, na_rm = TRUE, with_ties = FALSE) %>% select(id, col1_end = col1, max_end_day = end_day) # 合并两个结果 final_result <- inner_join(min_start_df, max_end_df, by = "id")
最终输出:
id col1_start min_start_day col1_end max_end_day <dbl> <chr> <dbl> <chr> <dbl> 1 1 a 1 b 15 2 2 d 4 e 22 3 3 f 5 g 21
方法2:用dplyr的mutate标记后筛选
在组内标记出符合条件的行,再通过summarise整理目标列:
library(dplyr) final_result <- df %>% group_by(id) %>% mutate( is_min_start = start_day == min(start_day, na.rm = TRUE), is_max_end = end_day == max(end_day, na.rm = TRUE) ) %>% filter(is_min_start | is_max_end) %>% summarise( col1_start = col1[is_min_start], min_start_day = start_day[is_min_start], col1_end = col1[is_max_end], max_end_day = end_day[is_max_end] ) %>% ungroup()
该方法结果与方法1完全一致。
方法3:用data.table快速实现
如果习惯使用data.table,可通过分组计算直接提取对应值:
library(data.table) setDT(df) final_result <- df[, .( col1_start = col1[which.min(start_day)], min_start_day = min(start_day, na.rm = TRUE), col1_end = col1[which.max(end_day)], max_end_day = max(end_day, na.rm = TRUE) ), by = id]
内容的提问来源于stack exchange,提问作者Joe the Second
相关产品推荐
相关产品推荐

