R中按ID分组查找首个非空提醒日期与末次应答日期的实现方法
R实现分组计算的两种方案
方案1:tidyverse(dplyr)实现
这是最贴近SAS by语句分组逻辑的实现方式,代码可读性高:
# 加载依赖包 library(dplyr) # 分组计算字段 dat_result <- dat %>% # 按id分组,等效于SAS的by id语句 group_by(id) %>% mutate( # 取组内最早的非空提醒日期 FirstDate = min(ReminderDate, na.rm = TRUE), # 仅取应答记录的最大日期 LastDate = max(date[status == "Answered"], na.rm = TRUE) ) %>% ungroup() # 处理全空分组的异常值(无提醒/无应答的id会返回Inf,转换为NA) dat_result <- dat_result %>% mutate( FirstDate = as.Date(ifelse(is.infinite(FirstDate), NA, FirstDate), origin = "1970-01-01"), LastDate = as.Date(ifelse(is.infinite(LastDate), NA, LastDate), origin = "1970-01-01") )
方案2:base R实现
无需安装额外依赖包,用原生ave函数完成分组运算:
# 计算首个提醒日期 dat$FirstDate <- ave(dat$ReminderDate, dat$id, FUN = function(x) min(x, na.rm = TRUE)) # 计算最后一次应答日期 dat$LastDate <- ave(1:nrow(dat), dat$id, FUN = function(idx) { group_data <- dat[idx, ] max(group_data$date[group_data$status == "Answered"], na.rm = TRUE) }) # 转换Inf为NA dat$FirstDate <- as.Date(ifelse(is.infinite(dat$FirstDate), NA, dat$FirstDate), origin = "1970-01-01") dat$LastDate <- as.Date(ifelse(is.infinite(dat$LastDate), NA, dat$LastDate), origin = "1970-01-01")
特殊场景适配说明
你提到的id=4的场景(最后一条是漏答记录且有提醒日期),上述两种方案的计算逻辑都自动适配:
- LastDate仅筛选
status == "Answered"的行取最大日期,最终返回2021-09-11,不受后续Missed行的影响 - FirstDate仍取最早的提醒日期2021-09-09,符合计算规则
内容的提问来源于stack exchange,提问作者AlpineNights
相关产品推荐
相关产品推荐

