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

如何在data.table中按组传播特定事件后的值?

问题:按组传播data.table中的特殊事件值

在data.table中按id分组,event列的基础值为1或-1。当出现非1/-1的特殊事件值时,需要将该值在组内向下传播,直到遇到下一个特殊事件为止。

提供的数据结构

temp_dt = structure(list(date = structure(c(18263L, 18264L, 18267L, 18268L, 
18269L, 18270L, 18271L, 18274L, 18275L, 18276L, 18277L, 18278L, 
18282L, 18283L, 18284L, 18285L, 18288L, 18289L, 18290L, 18291L, 
18292L, 18295L, 18296L, 18297L, 18298L, 18299L, 18302L, 18303L, 
18304L, 18305L, 18306L, 18310L, 18311L, 18312L, 18313L, 18316L, 
18317L, 18318L, 18319L, 18320L, 18323L, 18324L, 18325L, 18326L, 
18327L, 18330L, 18331L, 18332L, 18333L, 18334L, 18337L, 18338L, 
18339L, 18340L, 18341L, 18344L, 18345L, 18346L, 18347L, 18348L
), class = c("IDate", "Date")), id = c(43L, 43L, 43L, 43L, 43L, 
43L, 43L, 43L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 
44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 44L, 
44L, 44L, 44L, 44L, 44L, 44L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 
45L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 45L, 
45L, 45L, 45L), event = c(-1, -1, -1, -1, -1, -1, -1, -1, 1, 
1, 1, 1, 1, 1, -4, 1, 1, 1, 1, 1, 1, -2, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1)), row.names = c(NA, 
-60L), class = c("data.table", "data.frame"))

前20行数据预览:

> head(temp_dt, 20)
          date id event
 1: 2020-01-02 43    -1
 2: 2020-01-03 43    -1
 3: 2020-01-06 43    -1
 4: 2020-01-07 43    -1
 5: 2020-01-08 43    -1
 6: 2020-01-09 43    -1
 7: 2020-01-10 43    -1
 8: 2020-01-13 43    -1
 9: 2020-01-14 44     1
10: 2020-01-15 44     1
11: 2020-01-16 44     1
12: 2020-01-17 44     1
13: 2020-01-21 44     1
14: 2020-01-22 44     1
15: 2020-01-23 44    -4
16: 2020-01-24 44     1
17: 2020-01-27 44     1
18: 2020-01-28 44     1
19: 2020-01-29 44     1
20: 2020-01-30 44     1

期望输出结果

date id event signal
 1: 2020-01-02 43    -1     -1
 2: 2020-01-03 43    -1     -1
 3: 2020-01-06 43    -1     -1
 4: 2020-01-07 43    -1     -1
 5: 2020-01-08 43    -1     -1
 6: 2020-01-09 43    -1     -1
 7: 2020-01-10 43    -1     -1
 8: 2020-01-13 43    -1     -1
 9: 2020-01-14 44     1      1
10: 2020-01-15 44     1      1
11: 2020-01-16 44     1      1
12: 2020-01-17 44     1      1
13: 2020-01-21 44     1      1
14: 2020-01-22 44     1      1
15: 2020-01-23 44    -4     -4
16: 2020-01-24 44     1     -4
17: 2020-01-27 44     1     -4
18: 2020-01-28 44     1     -4
19: 2020-01-29 44     1     -4
20: 2020-01-30 44     1     -4
21: 2020-01-31 44     1     -4
22: 2020-02-03 44    -2     -2
23: 2020-02-04 44     1     -2
24: 2020-02-05 44     1     -2
25: 2020-02-06 44     1     -2
26: 2020-02-07 44     1     -2
27: 2020-02-10 44     1     -2
28: 2020-02-11 44     1     -2
29: 2020-02-12 44     1     -2
30: 2020-02-13 44     1     -2
31: 2020-02-14 44     1     -2
32: 2020-02-18 44     1     -2
33: 2020-02-19 44     1     -2
34: 2020-02-20 44     1     -2
35: 2020-02-21 44     1     -2
36: 2020-02-24 44     1     -2
37: 2020-02-25 44     1     -2
38: 2020-02-26 45    -1     -1
39: 2020-02-27 45    -2     -2
40: 2020-02-28 45    -1     -2
41: 2020-03-02 45    -1     -2
42: 2020-03-03 45    -1     -2
43: 2020-03-04 45    -1     -2
44: 2020-03-05 45    -1     -2
45: 2020-03-06 45    -1     -2
46: 2020-03-09 45    -1     -2
47: 2020-03-10 45    -1     -2
48: 2020-03-11 45    -1     -2
49: 2020-03-12 45    -1     -2
50: 2020-03-13 45    -1     -2
51: 2020-03-16 45    -1     -2
52: 2020-03-17 45    -1     -2
53: 2020-03-18 45     4      4
54: 2020-03-19 45    -1      4
55: 2020-03-20 45    -1      4
56: 2020-03-23 45    -1      4
57: 2020-03-24 45    -1      4
58: 2020-03-25 45    -1      4
59: 2020-03-26 45    -1      4
60: 2020-03-27 45    -1      4
          date id event signal

我的尝试及错误分析

尝试一

temp_dt[, signal:= ifelse(abs(event) == 1 & shift(abs(event)) != 1, shift(event), event) , by = id]

错误原因:仅处理了当前行是1/-1且上一行是特殊值的单次传播,无法将特殊值持续传递到后续所有行;组内首行会生成NA。

尝试二

temp_dt[, signal := {
  rn <- 1:.N
  i2 <- which(abs(event) != 1)
  fcase(
    rn %inrange% .(i2 + 1, i2 + 3), event,
    rn %in% i2, event
  )}, by = id]

错误原因:硬编码了固定的传播范围(仅3行),但实际需要传播到下一个特殊值前的所有行;未处理无特殊值的组,会产生大量NA。

尝试三

temp_dt[, signal := cummax(abs(event)), by = id]

错误原因:cummax取绝对值的累积最大值,丢失了原始值的符号;无法正确切换到下一个特殊值(比如id=44中-4之后的-2,累积最大值仍为4)。

简洁data.table解决方案

方法一:利用nafill填充

temp_dt[, signal := nafill(replace(event, abs(event) == 1, NA), type = "locf"), by = id]

解释:将所有1/-1替换为NA,再用locf(最近观测值向前填充)规则,用最近的非NA值(特殊值或组初始值)填充后续所有NA,实现特殊值的持续传播。

方法二:分组标记后填充

temp_dt[, grp := cumsum(abs(event) != 1), by = id]
temp_dt[, signal := event[1], by = .(id, grp)]
temp_dt[, grp := NULL] # 可选,删除临时分组列

解释:按id分组,用cumsum生成新的子分组标记(每次遇到特殊值就新增分组),然后每个子分组内取第一个值作为signal,自动完成特殊值的组内传播。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:17:33