R中的保留和滞后功能为SAS

use*_*962 7 r data.table

我正在寻找一个类似于R的函数lag1,lag2retain在SAS中使用我可以与data.tables一起使用的函数.

我知道R中有类似的功能embed,lag但它们不会返回单个值或前一个值.它们返回一组完整的向量.

R中有什么东西我可以用data.table吗?

有关SAS功能的更多信息:

Jor*_*eys 9

您必须意识到R的工作方式与SAS中的数据步骤非常不同.的lag在SAS功能在数据步骤中使用,并且被用于数据步骤的隐含的循环结构.这同样适用于对retain功能,通过数据的循环会时只需保持常数的值.

另一方面,R完全矢量化.这意味着您必须重新考虑您想要做的事情,并相应地进行调整.

  • retain在R中简单无用,因为R默认循环参数.如果要明确地执行此操作,您可能会查看例如rep()构造具有常量值和特定长度的向量.
  • lag是一个使用索引的问题,只是在向量中移动所有值的位置.为了保持相同长度的矢量,您需要添加一些NA并删除一些额外的值.

一个简单示例:此SAS代码滞后于变量x并添加year具有常量值的变量:

data one;
   retain year 2013;
   input x @@;
   y=lag1(x);
   z=lag2(x);
   datalines;
1 2 3 4 5 6
;
Run Code Online (Sandbox Code Playgroud)

在R中,您可以编写自己的滞后函数,如下所示:

mylag <- function(x,k) c(rep(NA,k),head(x,-k))
Run Code Online (Sandbox Code Playgroud)

该单行在向量的开头添加k倍NA,并从向量中删除最后的k个值.结果是lag1SAS中给出的滞后矢量等.

这允许类似的东西:

nrs <- 1:6 # equivalent to datalines
one <- data.frame(
   x = nrs,
   y = mylag(nrs,1),
   z = mylag(nrs,2),
   year = 2013  # R automatically loops, so no extra command needed
)
Run Code Online (Sandbox Code Playgroud)

结果是:

> one
  x  y  z year
1 1 NA NA 2013
2 2  1 NA 2013
3 3  2  1 2013
4 4  3  2 2013
5 5  4  3 2013
6 6  5  4 2013
Run Code Online (Sandbox Code Playgroud)

完全相同的data.table对象也适用.这里重要的注意事项是重新思考你的策略:不要像使用SAS中的DATA步骤那样循环思考,而是在使用R时必须开始考虑向量和索引.


Zac*_*ach 5

我想说的衣柜相当于retainlag1lag2将是滞后功能quantmod包

使用它非常容易data.tables。例如:

library(data.table)
library(quantmod)
d <- data.table(v1=c(rep('a', 10), rep('b', 10)), v2=1:20)
setkeyv(d, 'v1')
d[,new_var := Lag(v2, 1), by='v1']
d[,new_var2 := v2-Lag(v2, 3), by='v1']
d[,new_var3 := Next(v2, 2), by='v1']
Run Code Online (Sandbox Code Playgroud)

这产生以下结果:

print(d)
    v1 v2 new_var new_var2 new_var3
 1:  a  1      NA       NA        3
 2:  a  2       1       NA        4
 3:  a  3       2       NA        5
 4:  a  4       3        3        6
 5:  a  5       4        3        7
 6:  a  6       5        3        8
 7:  a  7       6        3        9
 8:  a  8       7        3       10
 9:  a  9       8        3       NA
10:  a 10       9        3       NA
11:  b 11      NA       NA       13
12:  b 12      11       NA       14
13:  b 13      12       NA       15
14:  b 14      13        3       16
15:  b 15      14        3       17
16:  b 16      15        3       18
17:  b 17      16        3       19
18:  b 18      17        3       20
19:  b 19      18        3       NA
20:  b 20      19        3       NA
Run Code Online (Sandbox Code Playgroud)

如您所见,Lag让您回顾过去,而Next让您展望未来。这两个函数都很好,因为它们用 NA 填充结果,使其与输入具有相同的长度。

如果您想获得更高级、更高的性能,您可以研究data.table对象的滚动连接。这与您所要求的略有不同,但在概念上是相关的,因此我必须分享如此强大和令人敬畏的内容。

从 data.table 开始:

library(data.table)
library(quantmod)
set.seed(42)
d1 <- data.table(
    id=c(rep('a', 10), rep('b', 10)), 
    time=rep(1:10,2), 
    value=runif(20))
setkeyv(d1, c('id', 'time'))
print(d1)

    id time     value
 1:  a    1 0.9148060
 2:  a    2 0.9370754
 3:  a    3 0.2861395
 4:  a    4 0.8304476
 5:  a    5 0.6417455
 6:  a    6 0.5190959
 7:  a    7 0.7365883
 8:  a    8 0.1346666
 9:  a    9 0.6569923
10:  a   10 0.7050648
11:  b    1 0.4577418
12:  b    2 0.7191123
13:  b    3 0.9346722
14:  b    4 0.2554288
15:  b    5 0.4622928
16:  b    6 0.9400145
17:  b    7 0.9782264
18:  b    8 0.1174874
19:  b    9 0.4749971
20:  b   10 0.5603327
Run Code Online (Sandbox Code Playgroud)

您有另一个要加入的 data.table,但并非所有时间索引都存在于第二个表中:

d2 <- data.table(
        id=sample(c('a', 'b'), 5, replace=TRUE), 
        time=sample(1:10, 5), 
        value2=runif(5))
setkeyv(d2, c('id', 'time'))
print(d2)
   id time      value2
1:  a    4 0.811055141
2:  a   10 0.003948339
3:  b    6 0.737595618
4:  b    8 0.388108283
5:  b    9 0.685169729
Run Code Online (Sandbox Code Playgroud)

常规合并会产生大量缺失值:

d2[d1,,roll=FALSE]
    id time      value2     value
 1:  a    1          NA 0.9148060
 2:  a    2          NA 0.9370754
 3:  a    3          NA 0.2861395
 4:  a    4 0.811055141 0.8304476
 5:  a    5          NA 0.6417455
 6:  a    6          NA 0.5190959
 7:  a    7          NA 0.7365883
 8:  a    8          NA 0.1346666
 9:  a    9          NA 0.6569923
10:  a   10 0.003948339 0.7050648
11:  b    1          NA 0.4577418
12:  b    2          NA 0.7191123
13:  b    3          NA 0.9346722
14:  b    4          NA 0.2554288
15:  b    5          NA 0.4622928
16:  b    6 0.737595618 0.9400145
17:  b    7          NA 0.9782264
18:  b    8 0.388108283 0.1174874
19:  b    9 0.685169729 0.4749971
20:  b   10          NA 0.5603327
Run Code Online (Sandbox Code Playgroud)

但是,data.table 允许您在主索引内向前滚动二级索引!

d2[d1,,roll=TRUE]
    id time      value2     value
 1:  a    1          NA 0.9148060
 2:  a    2          NA 0.9370754
 3:  a    3          NA 0.2861395
 4:  a    4 0.811055141 0.8304476
 5:  a    5 0.811055141 0.6417455
 6:  a    6 0.811055141 0.5190959
 7:  a    7 0.811055141 0.7365883
 8:  a    8 0.811055141 0.1346666
 9:  a    9 0.811055141 0.6569923
10:  a   10 0.003948339 0.7050648
11:  b    1          NA 0.4577418
12:  b    2          NA 0.7191123
13:  b    3          NA 0.9346722
14:  b    4          NA 0.2554288
15:  b    5          NA 0.4622928
16:  b    6 0.737595618 0.9400145
17:  b    7 0.737595618 0.9782264
18:  b    8 0.388108283 0.1174874
19:  b    9 0.685169729 0.4749971
20:  b   10 0.685169729 0.5603327
Run Code Online (Sandbox Code Playgroud)

这真是太酷了:旧的观察结果会及时向前滚动,直到被新的观察结果取代。如果要替换NA系列开始时的值,可以通过向后滚动第一个观察值来实现:

d2[d1,,roll=TRUE, rollends=c(TRUE, TRUE)]
    id time      value2     value
 1:  a    1 0.811055141 0.9148060
 2:  a    2 0.811055141 0.9370754
 3:  a    3 0.811055141 0.2861395
 4:  a    4 0.811055141 0.8304476
 5:  a    5 0.811055141 0.6417455
 6:  a    6 0.811055141 0.5190959
 7:  a    7 0.811055141 0.7365883
 8:  a    8 0.811055141 0.1346666
 9:  a    9 0.811055141 0.6569923
10:  a   10 0.003948339 0.7050648
11:  b    1 0.737595618 0.4577418
12:  b    2 0.737595618 0.7191123
13:  b    3 0.737595618 0.9346722
14:  b    4 0.737595618 0.2554288
15:  b    5 0.737595618 0.4622928
16:  b    6 0.737595618 0.9400145
17:  b    7 0.737595618 0.9782264
18:  b    8 0.388108283 0.1174874
19:  b    9 0.685169729 0.4749971
20:  b   10 0.685169729 0.5603327
Run Code Online (Sandbox Code Playgroud)

这些滚动连接绝对令人难以置信,我从未见过它们在任何其他开源包中实现(?data.table有关更多信息,请参阅参考资料)。关闭“SAS 大脑”并打开“R 大脑”需要一些时间,但是一旦您克服了最初的障碍,您就会发现该语言更具表现力。