data.table v1.9.5中shift()函数的奇怪行为 (R)

3

我正在使用当前data.table(v1.9.5)的开发版本,主要因为它拥有出色的内置shift()函数。

我注意到,在尝试在data.table调用中分组语句时,其中一个是对shift()的调用-我从中得到了一些奇怪的行为:

library(data.table)

foo = data.table(x = c(1, 5, 6 ,2, 9, 8))

foo[, y := {
        delta = c(NA, diff(x));
        lag = shift(x, n = 1L, fill = NA);
        list(delta/lag)}]

在添加y的尝试中,出现以下错误:
Error in delta/lag : non-numeric argument to binary operator

所以我只是创建了deltalag,而没有尝试进行任何交互,来检查我得到的内容:

foo[, c('delta', 'lag') := 
      list(c(NA, diff(x)),
           shift(x, n = 1L, fill = NA))]
foo
   x delta               lag
1: 1   NA  NA, 1, 5, 6, 2, 9
2: 5    4  NA, 1, 5, 6, 2, 9
3: 6    1  NA, 1, 5, 6, 2, 9
4: 2   -4  NA, 1, 5, 6, 2, 9
5: 9    7  NA, 1, 5, 6, 2, 9
6: 8   -1  NA, 1, 5, 6, 2, 9

如果我分开这些调用,我就可以得到我想要的结果:
foo[, delta := c(NA, diff(x))]
foo[, lag := shift(x, n = 1L, fill = NA)]

foo
   x delta lag
1: 1   NA   NA
2: 5    4    1
3: 6    1    5
4: 2   -4    6
5: 9    7    2
6: 8   -1    9

这是一个bug还是我漏了什么?

编辑:正如Pascal所指出的那样,我最初示例中的错误是由于shift()返回一个列表的结果。


3
shift 的输出是一个列表而不是向量。 - user3710546
我理解这一点。但是这个事实并没有解释(至少对我来说)在我调用shift()时,在语句组内和单独调用之间的区别。输出为列表会对此产生什么影响? - thagzone
1
尝试运行 c(1,2,3,4) / list(c(1,2,3,4)) 看看会发生什么。 - user3710546
我认为这是一个强有力的论点,支持shift返回向量而不是单元素列表。我建议添加一个FR - eddi
@Pascal 好的,这是一个很好的观点,肯定解释了这种行为。 @eddi 的确如此。至少对我来说,我已经遇到过几次这种情况了。我也可以看到当shift()返回一个列表时可能会很有用。也许应该能够指定输出类型。或者,正如我所理解的那样,它只在单元素列表的情况下返回一个向量。 - thagzone
显示剩余3条评论
1个回答

3

最近在v1.9.5版本中进行的提交(链接),使得shift()在向量输入时返回向量,且length(n) == 1。也就是说,当答案是长度为1的list时,我们为了方便起见返回一个向量。这使得我们可以做到:

DT[, col := shift(val, type = "lead")] # or "lag"

并且

DT[, col := valA + shift(valB, type="lead")] # or "lag"

在这两种情况下,返回一个向量,并且当RHS是原子时,为了方便起见,:=的右侧会在内部被包装为list(),从而得到预期的行为。
这解决了#1127问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接