如何计算不同按键列表的差异?

How to calculate the difference of a list of various by key?

我有一个带键的 data.table 和大约 1000 行,其中两行设置为键。我想创建一个名为 difference 的新变量,其中包含按键分组的每个数字行的差异。

例如简单数据为:ID和Act设置为key

    ID  ValueDate Act Volume
    1 2015-01-01 EUR     21
    1 2015-02-01 EUR     22
    1 2015-01-01 MAD     12
    1 2015-02-01 MAD     11
    2 2015-01-01 EUR      5
    2 2015-02-01 EUR      7
    3 2015-01-01 EUR      4
    3 2015-02-01 EUR      2
    3 2015-03-01 EUR      6

我想要的是:添加一个新列来计算每组两行(按时间排序)之间的差异,注意对于每个组的第一行,差异值为0。

    ID  ValueDate Act Volume Difference
    1 2015-01-01 EUR     21    0
    1 2015-02-01 EUR     22    1
    1 2015-01-01 MAD     12    0
    1 2015-02-01 MAD     11   -1
    2 2015-01-01 EUR      5    0
    2 2015-02-01 EUR      7    2
    3 2015-01-01 EUR      4    0
    3 2015-02-01 EUR      2   -2
    3 2015-03-01 EUR      6    4

下面是生成测试数据的代码:

    dd <- data.table(ID = c(1,1,1,1,2,2,3,3,3), 
                     ValueDate = c("2015-01-01", "2015-02-01", "2015-01-01","2015-02-01", "2015-01-01","2015-02-01","2015-01-01","2015-02-01","2015-03-01"),
                     Act = c("EUR","EUR","MAD","MAD","EUR","EUR","EUR","EUR","EUR"),
                     Volume=c(21,22,12,11,5,7,4,2,6))

为 table 设置密钥:

    setkey(dd, ID, Act)

查看数据:

    > dd
       ID  ValueDate Act Volume
    1  1 2015-01-01 EUR     21
    2  1 2015-02-01 EUR     22
    3  1 2015-01-01 MAD     12
    4  1 2015-02-01 MAD     11
    5  2 2015-01-01 EUR      5
    6  2 2015-02-01 EUR      7
    7  3 2015-01-01 EUR      4
    8  3 2015-02-01 EUR      2
    9  3 2015-03-01 EUR      6

所以,我们可以使用聚合函数来计算差值吗?或 .SD 的方法用于“数据子集,但我不知道如何按组计算两行之间的差异,请注意对于某些组,行数也可能不同,但我有之前尝试过使用 for(i in 0:x) 重新计算差异,但我认为这不是一个好方法:(

如果您想明确使用您的密钥,您可以将 key 调用传递给 by 参数

dd[, Difference := c(0L, diff(Volume)), by = key(dd)]
dd
#    ID  ValueDate Act Volume Difference
# 1:  1 2015-01-01 EUR     21          0
# 2:  1 2015-02-01 EUR     22          1
# 3:  1 2015-01-01 MAD     12          0
# 4:  1 2015-02-01 MAD     11         -1
# 5:  2 2015-01-01 EUR      5          0
# 6:  2 2015-02-01 EUR      7          2
# 7:  3 2015-01-01 EUR      4          0
# 8:  3 2015-02-01 EUR      2         -2
# 9:  3 2015-03-01 EUR      6          4

或者使用 data.table v 1.9.6+ 你也可以使用 shift 函数

dd[, Difference := Volume - shift(Volume, fill = Volume[1L]), by = key(dd)]

我们可以使用dplyr。按 'ID'、'Act' 分组后,我们创建 'Difference' 列作为该列的 'Volume' 和 lag 的差值。

library(dplyr)
dd %>%
  group_by(ID, Act) %>%
  mutate(Difference = Volume-lag(Volume))

编辑:如@DavidArenburg 所述,将 lag(Volume) 替换为 lag(Volume, default = Volume[1L]) 将为每个组中的第一个元素提供 0 而不是 NA。


或者使用 base R 中的 ave,我们可以执行 diff 并与 0 连接,以便长度相同。 diff returns 长度比原始向量的长度小一的向量。

with(dd, ave(Volume, ID, Act, FUN= function(x) c(0, diff(x)))