r data.table计算的多个条件

Alt*_*ton 6 r data.table

我有一个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))
Run Code Online (Sandbox Code Playgroud)

我想添加一个列'incr_cost',它从不同行中的成本中减去每行i中的成本,我将其称为行k,其中行k满足以下条件:

  • sim_k = sim_i
  • active_k = 1
  • j_k <j_i
  • 行k包含满足上述3个条件的所有行中的最大j个

对于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
Run Code Online (Sandbox Code Playgroud)

看起来这类似于shift的应用程序,除了不是按原样"移位"data.table,我想转移行减少的data.table,其中不符合我的条件的行被过滤掉.我很难理解如何识别具有小于当前行的最大j值的行(并且满足其他两个条件).

以下工作除了在选择行k时不考虑行是否处于活动状态:

dt[, incr_cost := cost - shift(cost, fill=NA), by=Sim]
Run Code Online (Sandbox Code Playgroud)

我正在使用r data.table,但也欢迎非data.table解决方案.谢谢!

Fra*_*ank 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
Run Code Online (Sandbox Code Playgroud)

这会查找元组.(active = 1, Sim = Sim, j = j - 1),当找不到完全匹配时,"滚动"到最后一个j适合的值,如果有的话.

这个怎么运作

jx[i, j],.SD只是对表本身的简写,"数据的子集".

j加入x[i, on=, roll=, j]......

  • 前缀x.*是指x(here,.SD)的列; 和类似的
  • i.*将是i(这里,元组)的列的前缀.

(OP的使用j可能会让人感到困惑.我的意思是j,这个论点在DT[i, j, ...].)