r data.table计算的多个条件

时间:2018-04-21 01:53:12

标签: 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))

我想添加一个列'incr_cost',从另一行的成本中减去每行i中的成本,我将其称为行k,其中行k符合以下条件:

  • sim_k = sim_i
  • active_k = 1
  • j_k&lt; 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

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

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

dt[, incr_cost := cost - shift(cost, fill=NA), by=Sim]

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

1 个答案:

答案 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.*作为名称可能会让人感到困惑。我的意思是ij中的参数。)