首页 > 解决方案 > R:残差数百个变量的最快方法

问题描述

我有一个大型数据集(~30m 观察,~800 个变量),我需要通过将每个变量回归到 3 个变量然后存储残差来对 700 个变量进行残差。这是我目前正在做的事情:

io_d[, (vars_to_residualize_list) := lapply(.SD, 
        function(X) {lm(X ~ X1 + X2 + X3)$residuals}),
        .SDcols = vars_to_residualize]

wherevars_to_residualize是要残差的变量列表,并且vars_to_residualize_list是残差的新名称列表。

这需要大约 70 个小时才能通过所有变量。

有没有更快的方法来做到这一点?

标签: rdata.tableregressionlapply

解决方案


也许这会帮助您减少时间,明显fastLm() 比 lm() 慢得多;稍微修改代码fLmSEXP以便能够提取残差。

library(Rcpp)
library(RcppArmadillo)
library(rbenchmark)
## start from SEXP, most conversions, longest code
src <- '
Rcpp::List fLmSEXP(SEXP Xs, SEXP ys) {
Rcpp::NumericMatrix Xr(Xs);
Rcpp::NumericVector yr(ys);
int n = Xr.nrow(), k = Xr.ncol();
arma::mat X(Xr.begin(), n, k, false);
arma::colvec y(yr.begin(), yr.size(), false);
// fit model y ~ X, extract residuals
arma::colvec coef = arma::solve(X, y);
arma::colvec res  = y - X*coef;
// return the results
return Rcpp::List::create(Rcpp::Named("coefficients")=coef,Rcpp::Named("res")=res);
}
'
cppFunction(code=src, depends="RcppArmadillo")

我创建我的数据框

df <- data.frame(replicate(3,sample(1:4,300000,rep=TRUE)))
df = cbind(X = rnorm(300000),df)
head(df)
           X X1 X2 X3
1  0.6269854  1  4  3
2  0.4641201  1  1  4
3 -0.5625020  3  1  4
4  0.0452215  2  1  2
5  2.2453335  3  3  2
6  0.4045328  1  3  3
m <- as.matrix(cbind(X = df[,1],cbind(I = 1,df[,2:4])))

我比较了两个函数的结果

benchmark(
lm_res = lm(X ~ X1 + X2 + X3, data = df)$residuals,
flm_res = fLmSEXP(m[,2:5],m[,1])$res, replications = 100)[,1:4]

    test replications elapsed relative
2 flm_res          100    4.14    1.00
1  lm_res          100   12.46    3.01

我希望这会有所帮助,或者至少给你一个方法。


推荐阅读