从 Rarmadillo 中的矩阵子集中获取元素

get an element from a subset of a matrix in Rarmadillo

我有一个很大的矩阵。我正在尝试通过动态变化的权重从中进行采样。由于它被迫在 R 中使用循环,我正在尝试在 Rcpp 中实现它,因此它有机会 运行 快一点。经过一些实验后,我想我已经弄清楚如何使用正确的权重随机获取索引。

诀窍是我在任何给定时间只从列的子集进行采样(如果在 C 中效率更高,这可以更改为行 - 矩阵实际上是对称的)。我的索引仅为该列子集定义。在 R 中,我会按照

的方式做一些事情
large_matrix[, columns_of_interest][index]

这很好用。我将如何使用 Rcpp/Armadillo 做同样的事情?我的猜测

cppFunction("arma::vec element_from_subset(arma::mat D, arma::uvec i, arma::uvec columns) {
  # arma::mat D_subset = D.cols(columns);
  return D.cols(columns).elem(i);

  }", depends = "RcppArmadillo")

无法编译(并且 .at 而不是 .elem 也不起作用,括号中围绕事物的标准 R 技巧也不起作用。

这确实有效,但这是我要避免的:

cppFunction("arma::vec element_from_subset(arma::mat D, arma::uvec i, arma::uvec columns) {
  arma::mat D_subset = D.cols(columns);
  return D_subset.elem(i);

  }", depends = "RcppArmadillo")

有什么方法可以做到这一点而不需要保存 D.cols(columns)?

简答:否

但是,问题的表述不正确。想想这里发生了什么:

(M <- matrix(1:9, 3, 3)) 
#>      [,1] [,2] [,3]
#> [1,]    1    4    7
#> [2,]    2    5    8
#> [3,]    3    6    9

columns_of_interest = 1:2
M[, columns_of_interest] 
#>      [,1] [,2]
#> [1,]    1    4
#> [2,]    2    5
#> [3,]    3    6 

从这里开始,如果 index 为 1,则我们得到:

index = 1
M[, columns_of_interest][index]
#> 1

因此,本质上,真正发生的是 (i,j) 的条目子集。因此,您应该只使用:

Rcpp::cppFunction("double element_from_subset(arma::mat D, int i, int j) { 
                  return D(i, j);
                  }", depends = "RcppArmadillo")
element_from_subset(M, 0, 0)
#> [1] 1

我是根据发布的 RC++ 代码说的,例如R 给出 1 个值,C++ 有一个 return 类型只允许一个值。


OP 发布的代码显示没有错误。编译后的初始错误将表明在 arma class 中使用 Rcpp 对象存在问题。如果我们更正类型,例如将 Rcpp::IntegerVector 替换为 arma 适当类型的 arma::ivecarma::uvec,然后编译会产生信息更丰富的错误消息。

更正后的代码:

Rcpp::cppFunction("double element_from_subset(arma::mat D, int i, arma::uvec columns) { 
  return D.cols(columns).elem(i);
  }", depends = "RcppArmadillo")

错误信息:

file6cf4cef8267.cpp:10:26: error: no member named 'elem' in 'arma::subview_elem2<double, arma::Mat<unsigned int>, arma::Mat<unsigned int> >'
  return D.cols(columns).elem(i);
         ~~~~~~~~~~~~~~~ ^
1 error generated.
make: *** [file6cf4cef8267.o] Error 1

因此,无法 subset a subview 是通过 subset 来自犰狳对象。


您可能想要阅读 Armadillo 的一些子集功能。他们非常有帮助。

免责声明:我贡献或编写的第一个和第二个链接。