如何在每个组中创建一个滞后变量?
我有一个data.table:
set.seed(1) data <- data.table(time = c(1:3, 1:4), groups = c(rep(c("b", "a"), c(3, 4))), value = rnorm(7)) data # groups time value # 1: b 1 -0.6264538 # 2: b 2 0.1836433 # 3: b 3 -0.8356286 # 4: a 1 1.5952808 # 5: a 2 0.3295078 # 6: a 3 -0.8204684 # 7: a 4 0.4874291
我想在 “组”的每个级别内计算“值”列的滞后版本。
结果应该看起来像
# groups time value lag.value # 1 a 1 1.5952808 NA # 2 a 2 0.3295078 1.5952808 # 3 a 3 -0.8204684 0.3295078 # 4 a 4 0.4874291 -0.8204684 # 5 b 1 -0.6264538 NA # 6 b 2 0.1836433 -0.6264538 # 7 b 3 -0.8356286 0.1836433
我试图直接使用lag
:
data$lag.value <- lag(data$value)
…这显然不会工作。
我也试过了:
unlist(tapply(data$value, data$groups, lag)) a1 a2 a3 a4 b1 b2 b3 NA -0.1162932 0.4420753 2.1505440 NA 0.5894583 -0.2890288
这几乎是我想要的。 但是,生成的矢量排序与data.table中的排序有所不同,这是有问题的。
在R,plyr,dplyr和data.table基础中,最有效的方法是什么?
你可以在data.table
做到这data.table
library(data.table) data[, lag.value:=c(NA, value[-.N]), by=groups] data # time groups value lag.value #1: 1 a 0.02779005 NA #2: 2 a 0.88029938 0.02779005 #3: 3 a -1.69514201 0.88029938 #4: 1 b -1.27560288 NA #5: 2 b -0.65976434 -1.27560288 #6: 3 b -1.37804943 -0.65976434 #7: 4 b 0.12041778 -1.37804943
对于多列:
nm1 <- grep("^value", colnames(data), value=TRUE) nm2 <- paste("lag", nm1, sep=".") data[, (nm2):=lapply(.SD, function(x) c(NA, x[-.N])), by=groups, .SDcols=nm1] data # time groups value value1 value2 lag.value lag.value1 #1: 1 b -0.6264538 0.7383247 1.12493092 NA NA #2: 2 b 0.1836433 0.5757814 -0.04493361 -0.6264538 0.7383247 #3: 3 b -0.8356286 -0.3053884 -0.01619026 0.1836433 0.5757814 #4: 1 a 1.5952808 1.5117812 0.94383621 NA NA #5: 2 a 0.3295078 0.3898432 0.82122120 1.5952808 1.5117812 #6: 3 a -0.8204684 -0.6212406 0.59390132 0.3295078 0.3898432 #7: 4 a 0.4874291 -2.2146999 0.91897737 -0.8204684 -0.6212406 # lag.value2 #1: NA #2: 1.12493092 #3: -0.04493361 #4: NA #5: 0.94383621 #6: 0.82122120 #7: 0.59390132
更新
从data.table
版本> = data.table
,我们可以使用shift
type
作为lag
或lead
。 默认情况下,类型是lag
。
data[, (nm2) := shift(.SD), by=groups, .SDcols=nm1] # time groups value value1 value2 lag.value lag.value1 #1: 1 b -0.6264538 0.7383247 1.12493092 NA NA #2: 2 b 0.1836433 0.5757814 -0.04493361 -0.6264538 0.7383247 #3: 3 b -0.8356286 -0.3053884 -0.01619026 0.1836433 0.5757814 #4: 1 a 1.5952808 1.5117812 0.94383621 NA NA #5: 2 a 0.3295078 0.3898432 0.82122120 1.5952808 1.5117812 #6: 3 a -0.8204684 -0.6212406 0.59390132 0.3295078 0.3898432 #7: 4 a 0.4874291 -2.2146999 0.91897737 -0.8204684 -0.6212406 # lag.value2 #1: NA #2: 1.12493092 #3: -0.04493361 #4: NA #5: 0.94383621 #6: 0.82122120 #7: 0.59390132
如果您需要相反的话,请使用type=lead
nm3 <- paste("lead", nm1, sep=".")
使用原始数据集
data[, (nm3) := shift(.SD, type='lead'), by = groups, .SDcols=nm1] # time groups value value1 value2 lead.value lead.value1 #1: 1 b -0.6264538 0.7383247 1.12493092 0.1836433 0.5757814 #2: 2 b 0.1836433 0.5757814 -0.04493361 -0.8356286 -0.3053884 #3: 3 b -0.8356286 -0.3053884 -0.01619026 NA NA #4: 1 a 1.5952808 1.5117812 0.94383621 0.3295078 0.3898432 #5: 2 a 0.3295078 0.3898432 0.82122120 -0.8204684 -0.6212406 #6: 3 a -0.8204684 -0.6212406 0.59390132 0.4874291 -2.2146999 #7: 4 a 0.4874291 -2.2146999 0.91897737 NA NA # lead.value2 #1: -0.04493361 #2: -0.01619026 #3: NA #4: 0.82122120 #5: 0.59390132 #6: 0.91897737 #7: NA
数据
set.seed(1) data <- data.table(time =c(1:3,1:4),groups = c(rep(c("b","a"),c(3,4))), value = rnorm(7), value1=rnorm(7), value2=rnorm(7))
使用包dplyr
:
library(dplyr) data <- data %>% group_by(groups) %>% mutate(lag.value = dplyr::lag(value, n = 1, default = NA))
给
> data Source: local data table [7 x 4] Groups: groups time groups value lag.value 1 1 a 0.07614866 NA 2 2 a -0.02784712 0.07614866 3 3 a 1.88612245 -0.02784712 4 1 b 0.26526825 NA 5 2 b 1.23820506 0.26526825 6 3 b 0.09276648 1.23820506 7 4 b -0.09253594 0.09276648
正如@BrianD所指出的,这隐含地假定值已经按组排序。 如果不是, order_by
组进行排序,或者在lag
使用order_by
参数。 另外请注意,由于dplyr的某些版本存在的问题 ,为了安全起见,应该明确给出参数和命名空间。
在基地R,这将做的工作:
data$lag.value <- c(NA, data$value[-nrow(data)]) data$lag.value[which(!duplicated(data$groups))] <- NA
第一行添加一串滞后的(+1)观察值。 第二个字符串纠正每个组的第一个条目,因为滞后的观察是来自前一个组。
请注意, data
格式为data.frame
,不能使用data.table
。