在Rcpp中从列表中索引元素

10
假设我在Rcpp中有一个名为x的List,其中包含矩阵。我可以使用x[0]或类似的方法提取其中一个元素。但是,如何提取该矩阵的特定元素呢?我最初想到的是x[0](0,0),但似乎行不通。我尝试使用*号,但也不起作用。
下面是打印矩阵的示例代码(显示可以轻松提取矩阵):
library("Rcpp")

cppFunction(
includes = ' 
NumericMatrix RandMat(int nrow, int ncol)
 {
  int N = nrow * ncol;
  NumericMatrix Res(nrow,ncol);
  NumericVector Rands  = runif(N);
   for (int i = 0; i < N; i++) 
  {
    Res[i] = Rands[i];
  }
  return(Res);
 }',

code = '
void foo()
{
  List x;
  x[0] = RandMat(3,3);
  Rf_PrintValue(wrap( x[0] )); // Prints first matrix in list.
}
')


foo()
我该如何修改这行代码Rf_PrintValue(wrap( x[0] ));以打印第一行第一列的元素?在我需要使用它进行计算的代码中,我需要提取此元素。
2个回答

9

快速回答:

  1. C++中的复合表达式有时可能会出问题;模板魔法会妨碍代码的执行。因此,只需将List对象分配给元素(例如NumericMatrix)即可。

  2. 然后根据需要从NumericMatrix中选择。我们可以访问行、列、元素等。

  3. 使用Rcpp::Rcout << anElement可以更容易地打印输出,但请注意,我们目前无法打印整个矩阵或向量——但是intdouble类型没有问题。

编辑:

这里是一个样例实现。

#include <Rcpp.h>

// [[Rcpp::export]]
double sacha(Rcpp::List L) {
    double sum = 0;
    for (int i=0; i<L.size(); i++) {
        Rcpp::NumericMatrix M = L[i];
        double topleft = M(0,0);
        sum += topleft;
        Rcpp::Rcout << "Element is " << topleft << std::endl;
    }
    return sum;    
}

/*** R
set.seed(42)
L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2))
sacha(L) # fix typo   
*/

并且它的结果:

R> Rcpp::sourceCpp('/tmp/sacha.cpp')

R> set.seed(42)

R> L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2))

R> sacha(L)
Element is 1.37096
Element is 1
Element is 1
[1] 3.37096
R>

6

在某些时候,你需要明确表达。 List 类不知道它所包含的元素类型,也不知道它是矩阵列表。

Dirk 已经向您展示了我们通常的做法,将元素作为 NumericMatrix 获取并处理矩阵。

这里有一种替代方案,假设您的列表所有元素都具有相同的结构,使用一个新的类模板:ListOf,提供足够的粘合剂使用户代码无缝使用。这只是将明确性移到了不同的位置。

#include <Rcpp.h>
using namespace Rcpp ;

template <typename WHAT>
class ListOf : public List {
public:
    template <typename T>
    ListOf( const T& x) : List(x){}

    WHAT operator[](int i){ return as<WHAT>( ( (List*)this)->operator[]( i) ) ; }

} ;

// [[Rcpp::export]]
double sacha( ListOf<NumericMatrix> x){
    double sum = 0.0 ; 
    for( int i=0; i<x.size(); i++){
        sum += x[i](0,0) ;    
    }
    return sum ;
}

/*** R
    L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2))
    sacha( L )
*/

当我sourceCpp这个文件时,我会得到:
> L <- list(matrix(rnorm(9), 3), matrix(1:9, 3), matrix(sqrt(1:4), 2))    
> sacha(L)
[1] 1.087057

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接