滞后于分组时间序列

机器算法验证 r 回归 时间序列 滞后
2022-03-05 00:58:11

我有数以万计的观察结果,它们在时间序列中,但按位置分组。例如:

location date     observationA observationB
---------------------------------------
 A       1-2010   22           12
 A       2-2010   26           15
 A       3-2010   45           16
 A       4-2010   46           27
 B       1-2010   167          48
 B       2-2010   134          56
 B       3-2010   201          53
 B       4-2010   207          42

我想看看 month x是否与 month x +1'sobservationA任何线性关系observationB

我做了一些研究并找到了一个zoo功能,但它似乎没有办法按组限制滞后。因此,如果我使用 zoo 并落后observationB1 行,我最终会将位置 A's lastobservationB作为位置 B's first observationB我宁愿让observationB任何位置中的第一个NA或其他一些明显的值来指示“不要碰这一行”。

我想我得到的是在 R 中是否有内置的方法来做到这一点?如果没有,我想我可以使用标准循环结构来完成这项工作。还是我什至需要操纵数据?

4个回答

有几种方法可以获得组内的滞后变量。首先,您应该对数据进行排序,以便在每个组中相应地对时间进行排序。

首先让我们创建一个示例 data.frame:

> set.seed(13)
> dt <- data.frame(location = rep(letters[1:2], each = 4), time = rep(1:4, 2), var = rnorm(8))
> dt
  location time        var
1        a    1  0.5543269
2        a    2 -0.2802719
3        a    3  1.7751634
4        a    4  0.1873201
5        b    1  1.1425261
6        b    2  0.4155261
7        b    3  1.2295066
8        b    4  0.2366797

定义我们的滞后函数:

 lg <- function(x)c(NA, x[1:(length(x)-1)])
  1. 然后可以使用以下方法计算组内变量的滞后tapply

     > unlist(tapply(dt$var, dt$location, lg))
        a1         a2         a3         a4         b1         b2         b3         b4 
        NA  0.5543269 -0.2802719  1.7751634         NA  1.1425261  0.4155261  1.2295066
    
  2. ddply从包plyr使用

    > ddply(dt, ~location, transform, lvar = lg(var))
      location time        var       lvar
    1        a    1 -0.1307015         NA
    2        a    2 -0.6365957 -0.1307015
    3        a    3 -0.6417577 -0.6365957
    4        a    4 -1.5191950 -0.6417577
    5        b    1 -1.6281638         NA
    6        b    2  0.8748671 -1.6281638
    7        b    3 -1.3343222  0.8748671
    8        b    4  1.5431753 -1.3343222  
    
  3. 使用data.tabledata.table的更快版本

     > ddt <- data.table(dt)
     > ddt[,lvar := lg(var), by = c("location")]
         location time        var       lvar
    [1,]        a    1 -0.1307015         NA
    [2,]        a    2 -0.6365957 -0.1307015
    [3,]        a    3 -0.6417577 -0.6365957
    [4,]        a    4 -1.5191950 -0.6417577
    [5,]        b    1 -1.6281638         NA
    [6,]        b    2  0.8748671 -1.6281638
    [7,]        b    3 -1.3343222  0.8748671
    [8,]        b    4  1.5431753 -1.3343222
    
  4. 使用lagplm中的函数

     > pdt <- pdata.frame(dt)
     > lag(pdt$var)
       a-1        a-2        a-3        a-4        b-1        b-2        b-3        b-4 
        NA  0.5543269 -0.2802719  1.7751634         NA  1.1425261  0.4155261  1.2295066
    
  5. 使用lagdplyr 中的函数

    > dt %>% group_by(location) %>% mutate(lvar = lag(var))        
    Source: local data frame [8 x 4]
    Groups: location        
      location time        var       lvar
    1        a    1  0.5543269         NA
    2        a    2 -0.2802719  0.5543269
    3        a    3  1.7751634 -0.2802719
    4        a    4  0.1873201  1.7751634
    5        b    1  1.1425261         NA
    6        b    2  0.4155261  1.1425261
    7        b    3  1.2295066  0.4155261
    8        b    4  0.2366797  1.2295066
    

最后两种方法需要从data.frame另一个对象转换,但您不必担心排序。我个人的偏好是最后一个,最初写答案时没有。

更新:更改了 data.table 代码以反映 @Hibernating 指出的 data.table 包的发展。

更新 2:添加了 dplyr示例。

@ mpiktas 只是在您的答案的第 3 版中简要提及两个小疏忽。首先,“更快的版本”这个词显然被错误地留下了。其次,代码中遗漏了“:=”这个词。修复后者修复了前者:=)

library(data.table);ddt <- data.table(dt)
f0<-function() plyr::ddply(dt,~location,transform,lvar=lg(var))
f1<-function() ddt[,transform(.SD,lvar=lg(var)),by=c("location")]
f2<-function() ddt[,lvar:=lg(var),by=location]
r0<-f0();r1<-f1();r2<-f2();all.equal(r0,r1,r2,check.attributes = FALSE)
boxplot(microbenchmark::microbenchmark(f0(),f1(),f2(),times=1000L))

在此处输入图像描述

这里有一个更快的方法,而不是完成所有tapply和额外的步骤:

dt<-data.frame(location=rep(letters[1:2],each=4),time=rep(1:4,2),var=rnorm(8))
lg<-function(x)c(NA,x[1:(length(x)-1)])
dt$lg <- ave(dt$var, dt$location, FUN=lg)

使用 dplyr

dt %>% group_by(location) %>% mutate(lvar=lag(var))