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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:54:07