R as SAS中的保留和滞后功能
我正在寻找一个类似于SAS中的R as SAS中的保留和滞后功能,r,data.table,R,Data.table,我正在寻找一个类似于SAS中的lag1、lag2和retain函数的函数,我可以在data.tables中使用这些函数 我知道R中有像embed和lag这样的函数,但它们不返回单个值或以前的值。它们返回一组完整的向量 R中是否有我可以用于data.table的内容 有关SAS功能的更多信息: 您必须知道,R的工作原理与SAS中的数据步骤非常不同。SAS中的lag函数用于数据步骤,并在该数据步骤的隐式循环结构中使用。retain函数也是如此,它只是在通过数据循环时保持值不变 另一方面,R完全
lag1
、lag2
和retain
函数的函数,我可以在data.tables中使用这些函数
我知道R中有像embed
和lag
这样的函数,但它们不返回单个值或以前的值。它们返回一组完整的向量
R中是否有我可以用于data.table的内容
有关SAS功能的更多信息:
lag
函数用于数据步骤,并在该数据步骤的隐式循环结构中使用。retain
函数也是如此,它只是在通过数据循环时保持值不变
另一方面,R完全矢量化。这意味着你必须重新思考你想做什么,并相应地适应
在R中毫无用处,因为R默认情况下会回收参数。如果您想显式地执行此操作,可以查看egretain
,以构造具有常量值和特定长度的向量rep()
是一个使用索引的问题,只是移动向量中所有值的位置。为了保持向量的长度相同,需要添加一些lag
并删除一些额外的值李>NA
x
,并添加具有常量值的变量year
:
data one;
retain year 2013;
input x @@;
y=lag1(x);
z=lag2(x);
datalines;
1 2 3 4 5 6
;
在R中,您可以编写自己的滞后函数,如下所示:
mylag <- function(x,k) c(rep(NA,k),head(x,-k))
结果是:
> 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
对于
data.table
对象,情况也完全相同。这里重要的一点是重新思考您的策略:在使用R时,您必须开始考虑向量和索引,而不是像SAS中的数据步骤那样进行循环思考。我想说,壁橱相当于retain
,lag1
,而lag2
将是最重要的
它很容易与数据表一起使用。例如:
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']
正如你所见,让你回顾过去,让你展望未来。这两个函数都很好,因为它们用NAs填充结果,使其与输入具有相同的长度
如果您想获得更高级、更高的性能,可以研究使用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
但是,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
这真是太酷了:旧的观察结果会随着时间向前滚动,直到被新的观察结果取代。如果要在序列开始时替换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
这些滚动连接绝对令人难以置信,我从未见过它们在任何其他开源软件包中实现(有关更多信息,请参见?data.table
)。关闭“SAS大脑”和打开“R大脑”需要一段时间,但一旦你克服了最初的困难,你会发现这种语言更具表现力。要保留,请尝试以下方法:
retain<-function(x,event,outside=NA)
{
indices <- c(1,which(event==TRUE), nrow(df)+1)
values <- c(outside,x[event==TRUE])
y<- rep(values, diff(indices))
}
retain以下是一个示例:使用sqldf累积值:
> w_cum <-
sqldf("select t1.id, t1.SomeNumt, SUM(t2.SomeNumt) as cum_sum
from w_cum t1
inner join w_cum t2 on t1.id >= t2.id
group by t1.id, t1.SomeNumt
order by t1.id
- 1111
- 21223
- 3 13 36
- 41450
- 51565
- 61681
- 71798
- 818116
- 919135
- 1020155
多年前,我们大多数R用户要么从未使用过SAS,要么烧掉了SAS手册来保暖。这些函数在SAS中做什么?Joris,我不想卷入编辑大战,但我做这些编辑是有原因的。这不是SAS问题,因此不需要标签;这个问题可以而且应该很容易地独立成一个关于R如何工作的问题,而不必提及SAS,除了提到lag函数,它可以帮助那些懂两种语言的人(以及对未来对lag有同样想法的用户的指南)。回答此问题的人不需要阅读SAS文档来回答此问题。@Joe OP的问题与他的SAS经验以及SAS和R之间的差异直接相关。只有当您知道SAS中的数据步骤是如何工作的,以及这与R方法有何不同时,他的问题才有意义。主要的问题是他的问题在R语境中没有意义;SAS中的LAG
函数返回的R-like中没有“先前记录”这样的内容。因此,我(直截了当地)反对你的编辑。对不起,如果我粗鲁无礼,那不是我的本意。我的社交能力没有那么强。幸运的是我的电脑可以处理;-)我非常同情来到R的SAS用户,他正试图复制保留。在我使用R的最初几个小时里,我搜索并找到了一个lag
函数,在尝试使用搞砸了的R时间序列对象时,我完全偏离了方向。NewRbies应该学习使用“zoo”软件包。@Joe SAS标签的使用是完全合理的,以便最大限度地查看可能独立使用R和SAS标签的人。查看SAS问题的人也可能具有回答此问题的R知识。我认为我们不需要为了一个标签就变得那么迂腐!
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
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
retain<-function(x,event,outside=NA)
{
indices <- c(1,which(event==TRUE), nrow(df)+1)
values <- c(outside,x[event==TRUE])
y<- rep(values, diff(indices))
}
df <- data.frame(w = c("a","b","c","a","b","c"), x = 1:6, y = c(1,1,2,2,2,3), stringsAsFactors = FALSE)
df$z<-retain(df$x-df$y,df$w=="b")
df
obtain<-function(x,event,outside=NA)
{
indices <- c(0,which(event==TRUE), nrow(df))
values <- c(x[event==TRUE],outside)
y<- rep(values, diff(indices))
}
df$z2<-obtain(df$x-df$y,df$w=="b")
df
> w_cum <-
sqldf("select t1.id, t1.SomeNumt, SUM(t2.SomeNumt) as cum_sum
from w_cum t1
inner join w_cum t2 on t1.id >= t2.id
group by t1.id, t1.SomeNumt
order by t1.id
id SomeNumt cum_sum