Home Articles

按组滚动回归

Asked
Viewed 1842 times
0

嗨,我有一个面板数据集 . 我想为每个公司做一个滚动窗口回归并提取独立变量的系数 . y是依赖var,x是独立var . 滚动窗口为12.即,第一个回归使用第1行到第12行数据,第二个回归使用第2行到第13行数据等 . 使用Rollapply .

这是一个与我遇到的完全相同的错误的问题:Rolling by group in data.table R关于这个问题的幸运之处在于它只需要一列但我的回归需要两列,所以我无法根据建议的答案进行更改帖子 . 这是另一篇使用for循环的帖子 . 我的真实数据有超过200万次观测,所以它太慢了:rolling regression with dplyr任何人都可以提供帮助吗?

我的假数据集如下:

dt<-rep(c("AAA","BBB","CCC"),each=24)
dt<-as.data.frame(dt)
names(dt)[names(dt)=="dt"] <- "firm"
a<-c(20100131,20100228,20100331,20100430,20100531,20100630,20100731,20100831,20100930,20101031,20101130,20101231,20110131,20110228,20110331,20110430,20110531,20110630,20110731,20110831,20110930,20111031,20111130,20111231)
dt$time<-rep(a,3)
dt<-dt%>% group_by(firm)%>%
  mutate(y=rnorm(24,10,5))
dt<-dt%>% group_by(firm)%>%
  mutate(x=rnorm(24,5,2))
dt<-as.data.table(dt)

我试过这段代码:

# create rolling regression function
    roll <- function(Z) 
{ 
  t = lm(formula=y~x, data = as.data.frame(Z), na.rm=T); 
  return(t$coef[2]) 
}
dt[,beta := rollapply(dt, width=12, roll, fill=NA, by.column=FALSE, align="right") , by=firm]

我正在尝试创建一个名为“beta”的列,显示var x的系数 . 因此,对于每个公司,第一个数据应该从第12个观察开始 .

对于不同的组,回归看起来像第一行的x和y,并且与我从EXCEL得到的结果相比,系数似乎有点偏差 .

我尝试的第二种方法是dplyr版本:

dt %>%
group_by(firm) %>%
mutate(dt,beta = rollapply(dt,12,function(x) coef(lm(y~x,data=as.data.frame(x)))[2],by.column= FALSE, fill = NA, align = "right"))

它给了我同样的问题 . 每组具有相同的编号 . 对于每个公司来说,回归从第1行开始采用y和x .

有什么想法吗?非常感谢 .

2 Answers

  • 1

    这是一个使用 rollRegres 包和 data.table 包的解决方案 . 我还添加了OP 's solution which works (see eddi'评论的修改版本,并使用了一个包含200万个观测值的示例作为OP提及

    #####
    # setup data
    library(rollRegres)
    library(data.table)
    library(dplyr)
    
    set.seed(33700919)
    n_firms <- 83334 # yields ~ the 2M firm as the OP mentions
    dt <- rep(1:n_firms, each = 24)
    dt <- data.frame(firm = dt)
    a <-c(20100131,20100228,20100331,20100430,20100531,20100630,20100731,20100831,20100930,20101031,20101130,20101231,20110131,20110228,20110331,20110430,20110531,20110630,20110731,20110831,20110930,20111031,20111130,20111231)
    dt$time <- rep(a, n_firms)
    dt <- dt %>% group_by(firm) %>% mutate(y=rnorm(24,10,5))
    dt <- dt %>% group_by(firm) %>% mutate(x=rnorm(24,5,2))
    dt <- as.data.table(dt)
    nrow(dt) # roughly the 2M rows that the OP mentions
    #R [1] 2000016
    
    #####
    # fit models
    setkey(dt, firm, time) # make sure data is sorted correctly
    start_time <- Sys.time() # to show computation time
    dt[
      , beta :=
        roll_regres.fit(x = cbind(1, .SD[["x"]]), y = .SD[["y"]],
                        width = 12L)$coefs[, 2],
      by = firm]
    Sys.time() - start_time
    #R Time difference of 6.526595 secs
    
    # gives the same as OP's solution with minor corrections
    library(zoo)
    start_time <- Sys.time()
    roll <- function(Z)
      lm.fit(x = cbind(1, Z[, "x"]), y = Z[, "y"])$coef[2]
    dt[
      , beta_zoo :=
        rollapply(.SD, width=12, roll, fill=NA, by.column=FALSE, align="right"),
      by=firm]
    Sys.time() - start_time # much slower
    #R Time difference of 1.87341 mins
    
    # gives the same
    all.equal(dt$beta, dt$beta_zoo)
    #R [1] TRUE
    
  • 0

    也许您可以尝试更改rollapply中的第一个参数,将 dt 替换为列, dt[, c("y","x")] . 看看它是否有效

Related