根据先前的值和 data.table 中的另一个变量填充一个变量

Populating a variable based on previous values and another variable in a data.table

我有订单和交易数据,需要计算订单发生交易后的剩余交易量。在下面的数据中,我们有相对于订单的交易量,交易发生在状态==2 时。

      Order Status Volume Traded RemainingVolume
 1:   412      1    100     NA              100
 2:   412      2     NA     46               NA
 3:   412      2     NA     15               NA
 4:   412      2     NA     39               NA
 5:   538      1     10     NA               10
 6:   538      2     NA      7               NA
 7:   538      2     NA      3               NA
 8:   592      1    389     NA              389
 9:   592      2     NA     95               NA
10:   648      1    100     NA              100
11:   648      2     NA    100               NA
12:   885      1     50     NA               50
13:   885      2     NA     47               NA
14:   885      2     NA      3               NA
15:   950      1     39     NA               39
16:   950      2     NA     39               NA

我只需要计算每个订单的剩余数量。这是通过从交易量中减去交易量(交易量)来计算的。由于开头的 RemainingVolume (status==1) 无论如何设置为 Volume,这就是 (RemainingVolume-Traded),即 全部。换句话说,我需要以下输出:

     Order Status Volume Traded RemainingVolume
 1:   412      1    100     NA              100
 2:   412      2     NA     46               54
 3:   412      2     NA     15               39
 4:   412      2     NA     39                0
 5:   538      1     10     NA               10
 6:   538      2     NA      7                3
 7:   538      2     NA      3                0
 8:   592      1    389     NA              389
 9:   592      2     NA     95              294
10:   648      1    100     NA              100
11:   648      2     NA    100                0
12:   885      1     50     NA               50
13:   885      2     NA     47                3
14:   885      2     NA      3                0
15:   950      1     39     NA               39
16:   950      2     NA     39                0

注意订单 412、538、592、648、885 和 950 的剩余交易量是如何成交的。假设数据在 table mz 中,rem 是 RemainingVolume,trdq 是已交易,我试过以下:

for (i in 2:nrow(mz)){
  if (is.na(mz[i]$rem))mz[i]$rem = mz[i-1]$rem - mz[i]$trdq
}

有效,但速度真的非常慢。这里的数据有数百万行,因此只有 data.table 解决方案是可行的。所以我尝试了:

mz[,rem:= ifelse(is.na(rem), shift(rem, 1)-trdq, rem), by = ord]

这里也没有答案。我得到了第一笔交易的 RemainingVolume,仅此而已。下面的交易仍然是 NA。我在这里错过了什么?我是 data.table 的新手,所以可能很简单。

考虑到数据的大小,性能在这里确实很关键。非常感谢任何帮助。

对于每个 Orderfirst RemainingVolume 中减去 Traded 的累积总和。

由于您的数据量很大,您可以在 data.table 中执行此操作:

library(data.table)

setDT(df)[,RemainingVolume := first(RemainingVolume) - 
                              c(0, cumsum(Traded[-1])), Order]
df

#    Order Status Volume Traded RemainingVolume
# 1:   412      1    100     NA             100
# 2:   412      2     NA     46              54
# 3:   412      2     NA     15              39
# 4:   412      2     NA     39               0
# 5:   538      1     10     NA              10
# 6:   538      2     NA      7               3
# 7:   538      2     NA      3               0
# 8:   592      1    389     NA             389
# 9:   592      2     NA     95             294
#10:   648      1    100     NA             100
#11:   648      2     NA    100               0
#12:   885      1     50     NA              50
#13:   885      2     NA     47               3
#14:   885      2     NA      3               0
#15:   950      1     39     NA              39
#16:   950      2     NA     39               0

baseR 的实现方式

dt$RemainingVolume <- ave(replace(dt$RemainingVolume, dt$Status ==2, -1*dt$Traded[dt$Status ==2]), dt$Order, FUN = function(x) cumsum(x))

dt
    Order Status Volume Traded RemainingVolume
 1:   412      1    100     NA             100
 2:   412      2     NA     46              54
 3:   412      2     NA     15              39
 4:   412      2     NA     39               0
 5:   538      1     10     NA              10
 6:   538      2     NA      7               3
 7:   538      2     NA      3               0
 8:   592      1    389     NA             389
 9:   592      2     NA     95             294
10:   648      1    100     NA             100
11:   648      2     NA    100               0
12:   885      1     50     NA              50
13:   885      2     NA     47               3
14:   885      2     NA      3               0
15:   950      1     39     NA              39
16:   950      2     NA     39               0

使用的示例数据

dt <- structure(list(Order = c(412L, 412L, 412L, 412L, 538L, 538L, 
538L, 592L, 592L, 648L, 648L, 885L, 885L, 885L, 950L, 950L), 
    Status = c(1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 
    2L, 2L, 1L, 2L), Volume = c(100L, NA, NA, NA, 10L, NA, NA, 
    389L, NA, 100L, NA, 50L, NA, NA, 39L, NA), Traded = c(NA, 
    46L, 15L, 39L, NA, 7L, 3L, NA, 95L, NA, 100L, NA, 47L, 3L, 
    NA, 39L), RemainingVolume = c(100, 54, 39, 0, 10, 3, 0, 389, 
    294, 100, 0, 50, 3, 0, 39, 0)), row.names = c(NA, -16L), class = "data.frame")