我有一个data.table,如下所示:
Sim j active cost
1: 1 1 1 100
2: 1 2 1 125
3: 1 3 0 200
4: 1 4 1 250
5: 2 1 1 100
6: 2 2 0 50
7: 2 3 0 125
8: 2 4 1 200
dt <- data.table(Sim = c(1, 1, 1, 1, 2, 2, 2, 2),
j = c(1, 2, 3, 4, 1, 2, 3, 4),
active = c(1, 1, 0, 1, 1, 0, 0, 1),
cost = c(100, 125, 200, 250, 100, 50, 125, 200))
我想添加一个列'incr_cost',从另一行的成本中减去每行i中的成本,我将其称为行k,其中行k符合以下条件:
对于j = 1的行,incr_cost可以只是NA。
在我的示例中,解决方案看起来像:
Sim j active cost incr_cost
1: 1 1 1 100 NA
2: 1 2 1 125 25
3: 1 3 0 200 75
4: 1 4 1 250 125
5: 2 1 1 100 NA
6: 2 2 0 50 -50
7: 2 3 0 125 25
8: 2 4 1 200 100
看起来这类似于shift的应用程序,除了不是按原样“移动”data.table,我想转移行减少的data.table,其中不符合我条件的行被过滤掉。我很难理解如何识别具有小于当前行的最大j值的行(并且满足其他两个条件)。
以下工作除了在选择行k时不考虑行是否处于活动状态:
dt[, incr_cost := cost - shift(cost, fill=NA), by=Sim]
我正在使用r data.table,但也欢迎非data.table解决方案。谢谢!
答案 0 :(得分:6)
您可以使用滚动连接:
dt[, v :=
cost - .SD[.(active = 1, Sim = Sim, j = j - 1), on=.(active, Sim, j), roll=TRUE, x.cost]]
Sim j active cost v
1: 1 1 1 100 NA
2: 1 2 1 125 25
3: 1 3 0 200 75
4: 1 4 1 250 125
5: 2 1 1 100 NA
6: 2 2 0 50 -50
7: 2 3 0 125 25
8: 2 4 1 200 100
这会查找元组.(active = 1, Sim = Sim, j = j - 1)
,当找不到完全匹配时,“滚动”到适合的最后j
值,如果有的话。
工作原理
在j
的{{1}}中,x[i, j]
只是表格本身的简写,即“数据子集”。
加入.SD
的{{1}} ...
j
是指x[i, on=, roll=, j]
的列(此处为x.*
);和类似的x
将是.SD
列(此处为元组)的前缀。 (OP使用i.*
作为名称可能会让人感到困惑。我的意思是i
,j
中的参数。)