在R中,我可以根据其索引提取矩阵元素,如下所示
> m <- matrix(1:6, nrow = 3)
> m
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
> row_index <- c(1, 2)
> col_index <- c(2, 2)
> m[cbind(row_index, col_index)]
[1] 4 5
Armadillo / Rcpp :: Armadillo有原生方式吗?我能做的最好的是一个自定义函数,它使用行和列索引来计算元素索引(见下文)。我大多担心自定义功能也不会表现良好。
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
NumericVector Rsubmatrix(arma::uvec rowInd, arma::uvec colInd, arma::mat m) {
arma::uvec ind = (colInd - 1) * m.n_rows + (rowInd - 1);
arma::vec ret = m.elem(ind);
return wrap(ret);
}
/*** R
Rsubmatrix(row_index, col_index, m)
/
答案 0 :(得分:1)
来自docs:
X.submat( vector_of_row_indices, vector_of_column_indices )
但似乎只返回矩阵块。对于非简单连接的区域,我认为您的解决方案是最好的,但您并不真正需要一个函数,
m.elem((colInd - 1) * m.n_rows + (rowInd - 1));
返回矢量没有任何问题。为清楚起见,您可以定义一个函数来处理行+ col到索引的转换,
inline arma::uvec arr2ind(arma::uvec c, arma::uvec r, int nrow)
{
return c * nrow + r;
}
// m.elem(arr2ind(colInd - 1, rowInd - 1, m.n_rows));
答案 1 :(得分:1)
我们试试吧......
特别是,您可以通过编写自己的循环来rowInd
和colInd
进行子集,以使用.(i,j)
子集运算符。否则,唯一的另一个选择是您建议开始提出问题的解决方案......
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// Optimized OP method
// [[Rcpp::export]]
arma::vec Rsubmatrix(const arma::mat& m, const arma::uvec& rowInd, const arma::uvec& colInd) {
return m.elem((colInd - 1) * m.n_rows + (rowInd - 1));
}
// Proposed Alternative
// [[Rcpp::export]]
arma::rowvec get_elements(const arma::mat& m, const arma::uvec& rowInd, const arma::uvec& colInd){
unsigned int n = rowInd.n_elem;
arma::rowvec out(n);
for(unsigned int i = 0; i < n; i++){
out(i) = m(rowInd[i]-1,colInd[i]-1);
}
return out;
}
其中:
m <- matrix(1:6, nrow = 3)
row_index <- c(1, 2)
col_index <- c(2, 2)
m[cbind(row_index, col_index)]
给出:
[1] 4 5
我们有:
get_elements(m, row_index, col_index)
,并提供:
[,1] [,2]
[1,] 4 5
修改强>
微基准:
microbenchmark(Rsubmatrix(m, row_index, col_index), get_elements(m, row_index, col_index), times = 1e4)
给予:
Unit: microseconds
expr min lq mean median uq max neval
Rsubmatrix(m, row_index, col_index) 2.836 3.111 4.129051 3.281 3.502 5016.652 10000
get_elements(m, row_index, col_index) 2.699 2.947 3.436844 3.115 3.335 716.742 10000
这些方法都是时间紧密的。请注意,后者应该更好,因为它避免了两个独立的循环(1.计算&amp; 2.到子集)以及为存储结果而创建的附加临时向量。
Per armadillo 7.200.0
发布时,sub2ind()
函数已获得采用矩阵表示法的功能。此函数通过2 x n
矩阵获取矩阵下标,其中n
表示要子集的元素数,并将它们转换为元素表示法。
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::rowvec matrix_locs(arma::mat M, arma::umat locs) {
arma::uvec eids = sub2ind( size(M), locs ); // Obtain Element IDs
arma::vec v = M.elem( eids ); // Values of the Elements
return v.t(); // Transpose to mimic R
}
调用 R :
cpp_locs <- locs - 1 # Shift indices from R to C++
(cpp_locs <- t(cpp_locs)) # Transpose matrix for 2 x n form
matrix_locs(M, cpp_locs) # Subset the matrix