使用rollapply同时返回滚动回归系数与R平方的性能优化咨询
优化实现方案
基于zoo::rollapply的无额外依赖优化版
这个版本完全基于你现有使用的函数修改,不需要安装其他包,解决你提出的两个问题:
library(data.table) library(zoo) # 示例数据构造 set.seed(123) dtset <- data.table(x = 11:30, y = rnorm(20)) win_width <- 10 # 单次调用同时计算系数和R² dtset[, c("coefficient", "rsquare") := rollapply( data = .SD, width = win_width, align = "right", fill = NA, by.column = FALSE, FUN = function(win_mat) { x_win <- win_mat[, 1] y_win <- win_mat[, 2] reg <- lm.fit(cbind(x_win, 1), y_win) beta_x <- reg$coefficients[[1]] r2 <- 1 - sum(reg$residuals^2) / sum((y_win - mean(y_win))^2) return(c(beta_x, r2)) } ), .SDcols = c("x", "y")]
问题对应说明
- 多列传入rollapply的实现:你之前使用.SD失败是因为没有设置
by.column = FALSE参数,rollapply默认会对每列单独执行滚动计算,加上该参数后会将.SD选中的多列按行组合为矩阵传入自定义函数,无需通过行号切片取数,减少索引开销。如果需要对多列执行同类计算,只需批量调整.SDcols和赋值的列名即可。 - 单次调用返回多值:rollapply支持自定义函数返回多元素向量,返回结果会自动拼接为多列矩阵,直接通过data.table的
:=赋值给对应列即可,避免重复拟合回归模型,直接减少一半计算量。
百万级数据极致优化方案
如果你的数据量达到百万行级别,推荐使用专门优化过的滚动回归包rollRegres,底层做了向量化优化,速度比rollapply实现快10倍以上:
library(rollRegres) win_width <- 10 dtset[, c("coefficient", "rsquare") := { fit_res <- roll_regres(y ~ x, data = .SD, width = win_width, do_compute = "r2") .(fit_res$coefficients[, "x"], fit_res$r.squared) }, .SDcols = c("x", "y")]
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

