在RcppArmadillo
的项目中,我有一些矩阵(例如mat A,B,C;)和一个S4对象,例如: D(来自R中的外部函数)。由于我需要在这些矩阵和D之间进行一些计算,我想转换" D"在RcppArmadillo
中使用合适的数据类型,例如arma::mat D
。
可能吗?这样做的最佳方法是什么?
这是一个类似的代码:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List func1(arma::mat A, arma::mat B){
// Incoming
Rcpp::List outcome;
arma::mat rvecs;
arma::vec rvals;
Rcpp::Environment Matrix("package:Matrix");
Rcpp::Function nearPD = Matrix["nearPD"];
// Computation
Rcpp::List PD=nearPD(B);
Rcpp::S4 D = PD["mat"];
eig_sym(rvals, rvecs, D);
arma::mat RI12_hat = rvecs * arma::diagmat(1.0/sqrt(rvals)) * rvecs.t();
arma::mat diff = A - D;
// Release results
outcome = Rcpp::List::create(Rcpp::Named("rvals") = rvals,
Rcpp::Named("RI12_hat") = RI12_hat,
Rcpp::Named("rvecs") = rvecs);
return outcome;
}
其中D是类dpoMatrix
的矩阵,计算的正定矩阵和错误消息是&#34; no matching for operator
&#34;。
答案 0 :(得分:3)
不幸的是,dpoMatrix
对象还没有as<>()
或wrap()
。但是,使用S4
类,我们可以提取必要的组件并使用armadillo's advanced ctor for matrices重用内存。首先,我们必须通过查看dpoMatrix
或构建示例来理解documentation for the underlying Matrix
class对象。
请考虑以下事项:
B <- matrix(1, 3,3); B[1,3] <- B[3,1] <- 0
n.B <- nearPD(B, corr=TRUE, do2eigen=FALSE)
str(n.B)
这给出了:
List of 7
$ mat :Formal class 'dpoMatrix' [package "Matrix"] with 5 slots
.. ..@ x : num [1:9] 1 0.761 0.157 0.761 1 ...
.. ..@ Dim : int [1:2] 3 3
.. ..@ Dimnames:List of 2
.. .. ..$ : NULL
.. .. ..$ : NULL
.. ..@ uplo : chr "U"
.. ..@ factors : list()
$ eigenvalues: num [1:3] 2.157 0.843 -0.679
$ corr : logi TRUE
$ normF : num 0.528
$ iterations : num 18
$ rel.tol : num 6.48e-08
$ converged : logi TRUE
- attr(*, "class")= chr "nearPD"
因此,我们可以从x
广告位中检索矩阵的值,并使用Dim
成员函数检索.slot("name_here")
广告位的维度。
话虽如此,我们将按照以下方式快速实施:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
Rcpp::List magic_func(arma::mat A, arma::mat B){
// Incoming
Rcpp::List outcome;
arma::mat rvecs;
arma::vec rvals;
Rcpp::Environment Matrix("package:Matrix"); // Load the Matrix package in R!
Rcpp::Function nearPD = Matrix["nearPD"]; // Extract nearPD() R function
// Compute with R function an S4 object
Rcpp::List PD = nearPD(B);
Rcpp::S4 D_s4 = PD["mat"];
// Convert the S4 object to an Armadillo matrix
Rcpp::NumericVector temp = Rcpp::NumericVector(D_s4.slot("x"));
Rcpp::NumericVector dims = D_s4.slot("Dim");
// Advanced armadillo matrix ctor that reuses memory
arma::mat D(temp.begin(), // pointer to NumericVector
dims[0], // Number of Rows
dims[1], // Number of Columns
false, // Avoid copying by disabling `copy_aux_mem`
true); // Bind memory by enabling `strict`
// Computation
eig_sym(rvals, rvecs, D);
arma::mat RI12_hat = rvecs * arma::diagmat(1.0/sqrt(rvals)) * rvecs.t();
arma::mat diff = A - D;
// Return result
outcome = Rcpp::List::create(Rcpp::Named("rvals") = rvals,
Rcpp::Named("RI12_hat") = RI12_hat,
Rcpp::Named("rvecs") = rvecs);
return outcome;
}
代码:
set.seed(27)
A = matrix(round(rnorm(9),2), 3, 3)
A = A + t(A)
B = matrix(1, 3, 3); B[1,3] <- B[3,1] <- 0
magic_func(A, B)
结果:
$rvals
[,1]
[1,] 2.414214e-08
[2,] 1.000000e+00
[3,] 2.414214e+00
$RI12_hat
[,1] [,2] [,3]
[1,] 1609.647 -2275.222 1608.647
[2,] -2275.222 3218.293 -2275.222
[3,] 1608.647 -2275.222 1609.647
$rvecs
[,1] [,2] [,3]
[1,] -0.5000000 -7.071068e-01 0.5000000
[2,] 0.7071068 -7.077672e-16 0.7071068
[3,] -0.5000000 7.071068e-01 0.5000000