在犰狳中插入柱子给出了不同的结果,因为在传入RcppArmadillo之前插入R,我做错了什么?

时间:2013-11-18 21:31:29

标签: c++ r rcpp armadillo

这是cpp文件:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;

// [[Rcpp::export]]
List mylm1(NumericVector yr, NumericMatrix Xr) {
    int n = Xr.nrow(), k = Xr.ncol();
    arma::mat X(Xr.begin(), n, k, true);
    Rcout << X << std::endl;
    arma::mat allOne(n, 1, arma::fill::ones);

    X.insert_cols(0, allOne);
    Rcout << X << std::endl;
    arma::colvec y(yr.begin(), yr.size(), true);

    arma::colvec coef = arma::solve(X, y);
    arma::colvec resid = y - X*coef;

    double sig2 = arma::as_scalar( arma::trans(resid)*resid/(n-k) );
    arma::colvec stderrest = arma::sqrt( sig2 * arma::diagvec( arma::inv(arma::trans(X)*X)) );
    arma::colvec tval = coef / stderrest;

    return Rcpp::List::create(
        Rcpp::Named("coefficients") = coef,
        Rcpp::Named("stderr")       = stderrest,
        Rcpp::Named("tval")         = tval
    ) ;


}

// [[Rcpp::export]]
List mylm2(NumericVector yr, NumericMatrix Xr) {
    int n = Xr.nrow(), k = Xr.ncol();
    arma::mat X(Xr.begin(), n, k, false);
    Rcout << X << std::endl;
    arma::colvec y(yr.begin(), yr.size(), false);
    arma::colvec coef = arma::solve(X, y);
    arma::colvec resid = y - X*coef;
    double sig2 = arma::as_scalar( arma::trans(resid)*resid/(n-k) );
    arma::colvec stderrest = arma::sqrt( sig2 * arma::diagvec( arma::inv(arma::trans(X)*X)) );
    return Rcpp::List::create(
        Rcpp::Named("coefficients") = coef,
        Rcpp::Named("stderr")       = stderrest
    ) ;
}

然后在R:

sourceCpp('b.cpp')
set.seed(1)
x = matrix(rnorm(100), 25, 4)
y = rnorm(25)
mylm1(y, x)
mylm2(y, cbind(1, x))
summary(lm(y~x))

mylm1(y, x)
#    1.0000  -0.6265  -0.0561   0.3981   0.2914
#    1.0000   0.1836  -0.1558  -0.6120  -0.4433
#    ...
#    1.0000  -1.9894  -0.1123  -0.9341  -1.2246
#    1.0000   0.6198   0.8811  -1.2536  -0.4734
# 
# 
# $stderr
#         [,1]
# [1,] 0.16765
# [2,] 0.18009
# [3,] 0.24104
# [4,] 0.15117
# [5,] 0.21064


mylm2(y, cbind(1, x))
#    1.0000  -0.6265  -0.0561   0.3981   0.2914
#    1.0000   0.1836  -0.1558  -0.6120  -0.4433
#    ...
#    1.0000  -1.9894  -0.1123  -0.9341  -1.2246
#    1.0000   0.6198   0.8811  -1.2536  -0.4734
# 
# $stderr
#         [,1]
# [1,] 0.17179
# [2,] 0.18454
# [3,] 0.24699
# [4,] 0.15490
# [5,] 0.21584

summary(lm(y~x))

# Coefficients:
#             Estimate Std. Error t value Pr(>|t|)
# (Intercept)   0.1122     0.1718    0.65     0.52
# x1            0.0499     0.1845    0.27     0.79
# x2            0.1076     0.2470    0.44     0.67
# x3           -0.0435     0.1549   -0.28     0.78
# x4           -0.1750     0.2158   -0.81     0.43

根据Rcout的输出,这两种方法最终生成相同的X矩阵,但是它们没有给出相同的立场错误,为什么?

1 个答案:

答案 0 :(得分:2)

您的标准错误公式是错误的。您忘记为添加的列调整k。矩阵实际上是相同的事实应该让你对其余的代码有点怀疑。

我已经在你对上一个问题的评论中提到过,你需要以不同方式对拦截和“无拦截”案件进行处理。这里标准错误和问题的根本原因与此相同。简而言之,矩阵运算没有问题,但是稍后提取和转换数据时会出现问题。

获取提示并阅读RcppArmadillo源代码 - fastLm.cpp代码和相应的R函数的组合非常简短。或者阅读有关如何计算线性最小二乘和各种分析的更精细细节。

哦,我对你的问题标题也有同样的反对意见。 RcppArmadillo再次没有错;然而,你的用法是。