Basic 'armadillo4r' usage
Ordinary Least Squares
The Ordinary Least Squares (OLS) estimator is \(\hat{\beta} = (X^tX)^{-1}(X^tY)\) for a design matrix \(X\) and an outcome vector \(Y\) (Hansen 2022).
The following code shows how to compute the OLS estimator using
Armadillo and sending data from R to C++ and viceversa using
cpp4r and armadillo4r (Sanderson and Curtin 2016):
#include <cpp4r.hpp>
#include <armadillo4r.hpp>
using namespace arma;
using namespace cpp4r;
[[cpp4r::register]] doubles_matrix<> ols_mat_(const doubles_matrix<>& x) {
// Convert from R to C++
Mat<double> Y = as_Mat(y); // Col<double> Y = as_Col(y); also works
Mat<double> X = as_Mat(x);
// Armadillo operations
Mat<double> XtX = X.t() * X; // X'X
Mat<double> XtX_inv = inv(XtX); // (X'X)^(-1)
Mat<double> beta = XtX_inv * X.t() * Y; // (X'X)^(-1)(X'Y)
// Convert from C++ to R
return as_doubles_matrix(beta);
}
The previous code includes the cpp4r and
armadillo4r libraries (armadillo4r calls Armadillo) to
allow interfacing C++ with R. It also loads the corresponding namespaces
in order to simplify the notation (i.e., using Mat instead
of arma::Mat), and the function as_Mat() and
as_doubles_mat() are provided by armadillo4r
to pass a matrix object from R to C++ and that Armadillo
can read and then pass it back to R.
The use of const and & are specific to
the C++ language and allow to pass data from R to C++ without copying
the data, and therefore saving time and memory.
armadillo4r provides flexibility and in the case of the
resulting vector of OLS coefficients, it can be returned as a matrix or
a vector. The following code shows how to create three functions to
compute the OLS estimator and return the result as a matrix or a vector
avoiding repeated code:
Mat<double> ols_(const doubles_matrix<>& y, const doubles_matrix<>& x) {
Mat<double> Y = as_Mat(y); // Col<double> Y = as_Col(y); also works
Mat<double> X = as_Mat(x);
Mat<double> XtX = X.t() * X; // X'X
Mat<double> XtX_inv = inv(XtX); // (X'X)^(-1)
Mat<double> beta = XtX_inv * X.t() * Y; // (X'X)^(-1)(X'Y)
return beta;
}
[[cpp4r::register]] doubles_matrix<> ols_mat_(const doubles_matrix<>& y,
const doubles_matrix<>& x) {
Mat<double> beta = ols_(y, x);
return as_doubles_matrix(beta);
}
[[cpp4r::register]] doubles ols_dbl_(const doubles_matrix<>& y,
const doubles_matrix<>& x) {
Mat<double> beta = ols_(y, x);
return as_doubles(beta);
}
In the previous code, the ols_mat_() function receives
inputs from R and calls ols_() to do the computation on C++
side, and ols_dbl_() does the same but it returns a vector
instead of a matrix.
Additional Examples
The package repository includes the directory
armadillo4rtest, which contains an R package that uses
Armadillo, and that provides additional examples for eigenvalues,
Cholesky and QR decomposition, and linear models.