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

如何在R的data.table中对difftime类型的均值进行取整?

解决data.table中difftime类型字段取整问题

在R的data.table对象mdt中,通过日期减法得到了以天为单位的difftime类型字段days_elapsed1和days_elapsed2。按组计算这两个字段的均值后,结果仍为difftime类型,但无法直接对其执行取整操作。以下提供基于base R或data.table的解决方案,不使用dplyr。

可复现代码

# 创建示例数据集
library(data.table)
tests <- c("test1", "test2")
prob_bucket <- c(0.5, 0.3)
person_id <- sample(101:110, size=30, replace=TRUE)
grp <- sample(0:1, size = 30, replace = TRUE)
month <- sample(1:12, size=30, replace=TRUE)
day <- sample(1:28, size=30, replace=TRUE)
year <- sample(2018:2022, size=30, replace=TRUE)
test <- sample(tests, 30, replace=TRUE, prob = prob_bucket)
mydt <- data.table(person_id, grp, month, day, year, test)
mydt[, test_date:= as.Date(paste(month, day, year, sep = "-"), 
                           format="%m-%d-%Y")]
mydt[test_date < as.Date("02-01-2019", format="%m-%d-%Y"), grp:=0]
mydt[test_date >= as.Date("02-01-2019", format="%m-%d-%Y"), grp:=1]
mydt[, grp := as.factor(grp)]
ss_a <- mydt[test=="test1"]
ss_b <- mydt[test=="test2"]
a <- round(runif(nrow(ss_a), 5.5, 8),1)
b <- sample(100:250, size=nrow(ss_b), replace=TRUE)
mydt[test=="test1", ind_test1:=1][test=="test1", test_value:=a]
mydt[test=="test2", ind_test2:=1][test=="test2", test_value:=b]
setorder(mydt, cols = "person_id", "grp")

# 识别test1的关键值
mydt[ind_test1==1, critical_date_test1:= max(test_date), by=.(person_id, grp)]
mydt[, critical_date_test1:=mean(critical_date_test1, na.rm=TRUE), by=.(person_id, grp)]
mydt[test_date==critical_date_test1, critical_value_test1:= test_value]
mydt[, critical_value_test1:=mean(critical_value_test1, na.rm=TRUE), by=.(person_id, grp)]

# 识别test2的关键值
mydt[ind_test2==1, critical_date_test2:= max(test_date), by=.(person_id, grp)]
mydt[, critical_date_test2:=mean(critical_date_test2, na.rm=TRUE), by=.(person_id, grp)]
mydt[test_date==critical_date_test2, critical_value_test2:= test_value]
mydt[, critical_value_test2:=mean(critical_value_test2, na.rm=TRUE), by=.(person_id, grp)]

# 计算固定日期与关键测试日期之间的间隔天数
fixed_date <-as.Date("2-1-2019", format="%m-%d-%Y")
mydt[grp==0, days_elapsed1 := fixed_date-critical_date_test1]
mydt[grp==1, days_elapsed1 := critical_date_test1-fixed_date]
mydt[grp==0, days_elapsed2 := fixed_date-critical_date_test2]
mydt[grp==1, days_elapsed2 := critical_date_test2-fixed_date]

# 合并数据
dt_summ1_collapsed <- mydt[, .SD[1], by=.(person_id, grp)] 
days_elapsed <- c("days_elapsed1", "days_elapsed2")
# 按组计算合并后数据中各字段的均值
dt_summ_collapsed2 <- dt_summ1_collapsed[, lapply(.SD, mean, na.rm=TRUE), 
                                         by=grp, .SDcols=days_elapsed]

# 两次失败的取整尝试
dt_summ_collapsed2[, .SD:=round(.SD, 0), .SDcols=days_elapsed]
dt_summ_collapsed2[, .SD:=round_date(.SD, "day"), .SDcols=days_elapsed]

失败原因说明

  • round()函数默认不支持difftime类型,直接调用不会生效
  • round_date()是lubridate包的函数,仅针对日期对象(Date/POSIXct)生效,无法处理difftime时间差类型

解决方案

方案1:保留difftime类型的取整

将difftime转换为数值型取整后,再转回difftime类型,保留时间单位属性:

# 对difftime字段取整并保留类型
dt_summ_collapsed2[, c(days_elapsed) := lapply(.SD, function(x) {
  as.difftime(round(as.numeric(x)), units = "days")
}), .SDcols = days_elapsed]

方案2:转换为数值型结果

如果不需要保留difftime类型,可以直接在计算均值时转换为数值,再取整:

# 重新计算均值并直接得到取整后的数值列
dt_summ_collapsed2 <- dt_summ1_collapsed[, lapply(.SD, function(x) {
  round(mean(as.numeric(x), na.rm = TRUE))
}), by=grp, .SDcols=days_elapsed]

内容的提问来源于stack exchange,提问作者sunflower

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:23:15