You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言分组滚动回归求助:提取x系数结果异常(data.table/dplyr)

解决分组滚动窗口回归提取系数的问题

咱们先明确你的核心需求:对每个firm组做窗口大小为12的滚动回归,提取自变量x的系数,同时要保证大数据(200万+行)下的运行效率。你之前遇到的问题根源是在rollapply里错误传入了整个数据集,而不是当前分组的子集,导致跨组调用数据或者重复使用同一组的初始数据。

错误原因分析

你之前的代码里,无论是data.table还是dplyr版本,都在rollapply里直接用了dt,这会导致函数每次都调用整个数据集,而不是当前分组的行。比如在data.table的by=firm分组操作中,rollapply(dt, ...)并没有使用当前组的子集,而是全局的dt,这就会出现跨组取数的问题;dplyr版本同理,rollapply(dt, ...)没有引用当前分组的本地数据,所以每个组都用了相同的全局数据,导致beta值完全一致。

正确实现方案

1. Data.table 高效版本(推荐大数据场景)

我们需要在分组操作中,对当前组的.SD(Subset of Data)应用rollapply,同时用更高效的lm.fit代替lm来减少开销(lm会生成很多额外的统计输出,大数据下会拖慢速度)。

library(data.table)
library(zoo)

# 生成模拟数据(和你的代码逻辑一致,简化写法)
dt <- data.table(
  firm = rep(c("AAA","BBB","CCC"), each=24),
  time = rep(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), 3),
  y = rnorm(72, 10, 5),
  x = rnorm(72, 5, 2)
)

# 定义高效的滚动回归函数:用lm.fit代替lm,仅计算所需系数
roll_reg <- function(df) {
  # 构造包含截距项的X矩阵
  X <- cbind(1, df$x)
  y <- df$y
  # 仅当窗口内数据完整(无NA)且窗口大小符合要求时计算,否则返回NA
  if (sum(is.na(X)) + sum(is.na(y)) == 0 && nrow(df) == 12) {
    coefs <- lm.fit(X, y)$coefficients[2]
  } else {
    coefs <- NA_real_
  }
  return(coefs)
}

# 按firm分组,对每组的子集应用rollapply
dt[, beta := rollapply(.SD, width = 12, FUN = roll_reg, 
                       by.column = FALSE, align = "right", fill = NA), 
   by = firm]

2. Dplyr 版本

在dplyr中,需要用cur_data()来引用当前分组的本地数据集,而不是全局的dt:

library(dplyr)
library(zoo)

dt %>%
  group_by(firm) %>%
  mutate(beta = rollapply(cur_data(), width = 12, 
                          FUN = function(df) {
                            if (nrow(df) == 12 && all(!is.na(df$x)) && all(!is.na(df$y))) {
                              coef(lm(y ~ x, data = df))[2]
                            } else {
                              NA_real_
                            }
                          },
                          by.column = FALSE, align = "right", fill = NA)) %>%
  ungroup()

大数据优化建议

如果你的数据超过200万行,上面的rollapply+lm.fit已经比原生lm快很多,但还可以进一步优化:

  • 用data.table自带的frollapply,它比zoo的rollapply更快,不过需要把数据整理成矩阵形式处理。
  • 避免在滚动函数里做数据框转换,直接传递向量或者矩阵。
  • 如果允许近似或者不需要严格的OLS,可以考虑用递归最小二乘法,速度会提升几个数量级。

验证后你会发现:每个firm的第12行开始会有有效系数,前11行为NA,且不同组的beta值会有差异,和Excel的计算结果一致。

内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:41:35