时间序列面板数据中的普遍滞后现象

13

我有一个类似于这样的数据集

User    Date        Value
A       2012-01-01  4
A       2012-01-02  5   
A       2012-01-03  6
A       2012-01-04  7
B       2012-01-01  2
B       2012-01-02  3   
B       2012-01-03  4
B       2012-01-04  5

我想要创建一个 Value 的延迟,考虑到 User

User    Date        Value   Value.lag
A       2012-01-01  4       NA
A       2012-01-02  5       4
A       2012-01-03  6       5
A       2012-01-04  7       6
B       2012-01-01  2       NA
B       2012-01-02  3       2   
B       2012-01-03  4       3
B       2012-01-04  5       4

我已经用循环方式完成了它,但效率非常低。

df$value.lag1<-NA
levs<-levels(as.factor(df$User))
levs
  for (i in 1:length(levs)) {
    temper<- subset(df,User==as.numeric(levs[i]))
    temper<- rbind(NA,temper[-nrow(temper),])  
df$value.lag1[df$User==as.numeric(as.character(levs[i]))]<- temper
      }

但这很慢。我尝试过使用bytapply,但并没有找到如何让它们工作的方法。

我认为XTS或TS不适用于User元素。

有什么建议吗?


我认为plm包有对这种类型数据的实现。 - Seb
8个回答

9
你可以使用 ddply :将数据框切成几块,并转换每一块。
d <- data.frame( 
  User = rep( LETTERS[1:3], each=10 ),
  Date = seq.Date( Sys.Date(), length=30, by="day" ),
  Value = rep(1:10, 3)
)
library(plyr)
d <- ddply( 
  d, .(User), transform,
  # This assumes that the data is sorted
  Value = c( NA, Value[-length(Value)] ) 
)

1
根据https://dev59.com/H3M_5IYBdhLWcg3wn0vT的指导,可以使用`arrange()`对数据框进行排序。 - Konstantinos
这是对我最有效的解决方案!您能展示如何使用相同的过程,但是领先而不是滞后吗?我的面板数据中,所有参与者的时间点并不统一。 - rais

8
我认为最简单的方法,尤其是考虑进一步分析的时候,是将您的数据框从plm包转换为pdata.frame类。
转换后,可以使用diff()lag()运算符来创建面板差异和滞后。
df<-pdata.frame(df,index=c("id","date"))  
df<-transform(df, l_value=lag(value,1))   

优雅的答案 - 在将其转换为 pdata.frame 后,仅使用 lag() 来计算时间滞后作为新变量也可行! - Makosak

2
对于没有缺失观测值的面板,这是一个直观的解决方案:
df <- data.frame(id = c(1, 1, 1, 1, 1, 2, 2), 
                 date = c(1992, 1993, 1991, 1990, 1994, 1992, 1991), 
                 value = c(4.1, 4.5, 3.3, 5.3, 3.0, 3.2, 5.2))

df<-df[with(df, order(id,date)), ]  # sort by id and then by date
df$l_value=c(NA,df$value[-length(df$value)]) # create a new var with data displaced by 1 unit
df$l_value[df$id != c(NA, df$id[-length(df$id)])] =NA # NA data with different current and lagged id.
df

id date value l_value
4  1 1990   5.3      NA
3  1 1991   3.3     5.3
1  1 1992   4.1     3.3
2  1 1993   4.5     4.1
5  1 1994   3.0     4.5
7  2 1991   5.2      NA
6  2 1992   3.2     5.2

2

我遇到了类似的问题,并编写了一个函数。

#df needs to be a structured balanced paneldata set sorted by id and date
#OBS the function deletes the row where the NA value would have been.

df <- data.frame(id = c(1, 1, 1, 1, 1, 2, 2,2,2,2), 
                 date = c(1992, 1993, 1991, 1990, 1994, 1992, 1991
                          ,1994,1990,1993), 
                 value = c(4.1, 4.5, 3.3, 5.3, 3.0, 3.2, 5.2,5.3,3.4,5.6))
# sort paneldata set
library(dplyr)
df<-arrange(df,id,date)

#Function
# a=df
# b=colname of variable/variables that you want to lag
# q=number of lag years
# t=colname of date/time column
retraso<-function(a,b,q,t){

  sto<-max(as.numeric(unique(a[[t]])))
  sta<-min(as.numeric(unique(a[[t]])))

  yo<-a[which(a[[t]]>=(sta+q)),]

  la<-function(a,d,t,sto,sta){


    ja<-data.frame(a[[d]],a[[t]])
    colnames(ja)<-c(d,t)


    ja<-ja[which(ja[[t]]<=(sto-q)),1]
    return(ja)
  }

  for (i in 1:length(b)){

    yo[[b[i]]] <-la(a,b[i],t,sto,sta)

    }
    return(yo)

  }

#lag df 1 year
df<-retraso(df,"value",1,"date")


1
如果时间变量中没有间隔,则执行以下操作:

df %>% group_by(User) %>% mutate(value_lag = lag(value, order_by =Date)

如果您的时间变量存在间隙,请参考此答案https://dev59.com/TF8e5IYBdhLWcg3whqzl#26108191

0

collapse软件包现已在CRAN上提供,它提供了最通用的基于C/C++的解决方案,用于(完全识别的)面板滞后、领先、差分和增长率/对数差分。它具有通用函数flagfdifffgrowth以及相关的滞后/领先、差分和增长运算符LFDG。因此,要对面板数据集进行滞后处理,只需输入:

L(data, n = 1, by = ~ idvar, t = ~ timevar, cols = 4:8)

这意味着:计算data的第4到8列的1阶滞后,由idvartimevar标识。可以提供多个ID和时间变量,例如~ id1 + id2,并且还可以在每个列上计算滞后和超前的序列(即n = -1:3计算一个超前和3个滞后)。也可以使用flag更加程序化地完成相同的操作:

flag(data[4:8], 1, data$idvar, data$timevar)

这两个选项在典型数据集(<30,000 obs.)上计算时间都低于1毫秒。大数据性能类似于data.table的shift。类似的编程适用于差异fdiff / D和增长率fgrowth / G。这些函数都是S3通用的,具有向量/时间序列、矩阵/ts-矩阵、数据框以及plm::pseriesplm::pdata.framegrouped_df方法。因此,它们可以与面板数据的plm类一起使用,并与dplyr一起使用。


0

同样地,您可以使用tapply

# Create Data
user = c(rep('A',4),rep('B',4))
date = rep(seq(as.Date('2012-01-01'),as.Date('2012-01-04'),1),2)
value = c(4:7,2:5) 
df = data.frame(user,date,value)
# Get lagged values
df$value.lag = unlist(tapply(df$value, df$user, function(x) c(NA,x[-length(df$value)])))

这个想法完全相同:获取值,按用户拆分,然后在每个子集上运行函数。unlist将其带回向量格式。


0

如果表按用户和日期排序,则可以使用zoo完成此操作。诀窍是此时不指定索引。

library(zoo)
df <-read.table(text="User Date Value
A 2012-01-01 4
A 2012-01-02 5
A 2012-01-03 6
A 2012-01-04 7
B 2012-01-01 2
B 2012-01-02 3
B 2012-01-03 4
B 2012-01-04 5", header=TRUE, as.is=TRUE,sep = " ")

out <-zoo(df)

Value.lag <-lag(out,-1)[out$User==lag(out$User)]
res <-merge.zoo(out,Value.lag)
res <-res[,-(4:5)]  # to remove extra columns

  User.out Date.out   Value.out Value.Value.lag
1 A        2012-01-01 4         <NA>           
2 A        2012-01-02 5         4              
3 A        2012-01-03 6         5              
4 A        2012-01-04 7         6              
5 B        2012-01-01 2         <NA>           
6 B        2012-01-02 3         2              
7 B        2012-01-03 4         3              
8 B        2012-01-04 5         4 

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