如何按键计算各种列表的差异?

时间:2015-12-01 10:56:12

标签: r data.table key grouping

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

例如,简单数据是:ID和Act设置为键

    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))

为表格设置密钥:

    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的方法用于&#34;数据的子集,但我不知道如何按组计算两行之间的差异,请注意,对于某些组,行数可能不同,如好吧,但我之前尝试过使用 for(i in 0:x)来重新计算差异,但我认为这不是一个好方法:(

2 个答案:

答案 0 :(得分:4)

如果您想明确使用密钥,可以将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)]

答案 1 :(得分:2)

我们可以使用dplyr。在按“ID”,“行动”进行分组后,我们将“差异”列创建为该列的“卷”和lag的差异。

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

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

或者来自ave的{​​{1}},我们可以执行base R并与diff连接,以便长度相同。 0返回一个长度比原始向量长度小的向量。

diff