如果你想要做一些瘋狂的樣子,你應該使用RCPP:
library(RcppEigen)
library(inline)
incl <- '
using Eigen::LLT;
using Eigen::Lower;
using Eigen::Map;
using Eigen::MatrixXd;
using Eigen::MatrixXi;
using Eigen::Upper;
using Eigen::VectorXd;
using Eigen::Vector3d;
typedef Map<MatrixXd> MapMatd;
typedef Map<MatrixXi> MapMati;
typedef Map<VectorXd> MapVecd;
inline MatrixXd AtA(const MatrixXd& A) {
int n(A.cols());
return MatrixXd(n,n).setZero().selfadjointView<Lower>().rankUpdate(A.adjoint());
}
'
body <- '
const MapMatd X(as<MapMatd>(XX));
const MapVecd y(as<MapVecd>(yy));
const int n(X.rows()), m(X.cols());
LLT<MatrixXd> llt;
MatrixXd Res(n*n,m), Xbar(n,m);
Vector3d betahat;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
Xbar=X;
for (int k = 0; k < n; ++k) {
Xbar(k,1) -= X(i,1);
Xbar(k,2) -= X(j,2);
};
llt=AtA(Xbar);
betahat =llt.solve(Xbar.adjoint() * y);
Res.row(i*n+j) = betahat;
};
};
return wrap(Res);
'
crazyLm <- cxxfunction(signature(XX = "matrix", yy = "numeric"),
body, "RcppEigen", incl)
set.seed(1)
n=4
y=rnorm(n)
x1=rnorm(n)
x2=rnorm(n)
lm.ft=function(y,x1,x2) lm.fit(cbind(1,x1.bar,x2.bar), y)$coef
res=array(,dim=c(3,n,n))
for(i in 1:n)
for(j in 1:n){
x1.bar=x1-x1[i]
x2.bar=x2-x2[j]
res[,i,j]=lm.ft(y,x1.bar,x2.bar)
}
res2 <- aperm(array(t(crazyLm(cbind(1,x1,x2), y)), dim=c(3,n,n)), c(1,3,2))
all.equal(res, res2)
#[1] TRUE
system.time({
set.seed(1)
n=1000
y=rnorm(n)
x1=rnorm(n)
x2=rnorm(n)
res <- aperm(array(t(crazyLm(cbind(1,x1,x2), y)), dim=c(3,n,n)), c(1,3,2))
})
# User System elapsed
#36.130 0.033 36.158
這可以讓你適應百萬車型在不到一分鐘。但是,我沒有看到一個用例。
你不可能期望它在'n'中的增長幅度小於二次方。這個例子將需要3,000,000個單獨的調用到'lm.fit'。你應該解釋你正在做什麼,(或被要求做),並請指出這是你的家庭作業問題。 –
@IShouldBuyABoat我只給lm.fit打了100萬個電話,但這肯定夠用了。 OP沒有意識到98%以上的時間都花在了'lm.fit'裏面。 –
同意。我正在尋找第二個指數來暗淡()和相乘。如果我能想出實際的目標,我想這可能是通過對單個lm.fit進行簡單的增量調整來解決的。 –