R data.table按组统计当前RoundNo+1的历史出现次数实现方法
R实现方案(基于data.table)
前置说明
你提供的示例已经使用了data.table结构,我们直接基于该结构实现需求,核心逻辑为:先按投资者分组、按日期升序排序后,逐行统计当前行RoundNo+1在分组内当前行之前所有记录中的出现次数。
实现代码
基础版本(可读性高,适合中小数据量)
library(data.table) # 构造原始数据 dt = as.data.table(cbind(c(rep(1,7),rep(2,7)), c("2019-08-01","2019-09-01","2019-10-01","2019-11-01","2019-12-01","2021-04-01","2021-10-01", "2019-01-01","2019-02-01","2019-04-01","2019-08-01","2019-09-01","2019-10-01","2019-11-01"), c(2,1,2,2,1,3,2,1,2,3,2,1,3,1))) names(dt) = c("InvestorID","date","RoundNo") wanted = c(0,1,0,0,3,0,1,0,0,0,1,2,0,2) # 数据预处理:转换日期格式、按要求排序 dt[, date := as.Date(date)] setorder(dt, InvestorID, date) # 计算目标列 dt[, target := sapply(1:.N, function(i) { target_val = as.integer(RoundNo[i]) + 1 sum(RoundNo[1:(i-1)] == target_val, na.rm = TRUE) }), by = InvestorID] # 验证结果与手动生成的wanted列完全一致 identical(dt$target, as.integer(wanted)) # 运行返回TRUE
优化版本(性能更高,适合大数据量)
使用vapply替代sapply,明确返回值类型,运行效率更高:
dt[, target := { rn = as.integer(RoundNo) vapply(seq_along(rn), function(k) sum(head(rn, k-1) == rn[k] + 1), FUN.VALUE = integer(1)) }, by = InvestorID]
内容的提问来源于stack exchange,提问作者afinch
相关产品推荐
相关产品推荐

