矩阵的命名索引

Named indexing for a matrix

我正在尝试用名称索引矩阵。通常的方法报错:

NumericMatrix mytest(NumericVector v) {
  NumericMatrix ans(v.length(), v.length());
  rownames(ans) = v;
  float y = ans("1",0);
  NumericVector x = ans.row("1");
  return (ans);
}

我查看了 Matrix.h 和 rcpp 中的矩阵单元测试,但找不到类似的示例。此邮件列表 question 也没有提供执行此操作的方法。

我可以编写自己的代码来为矩阵编制索引吗,或许使用 R 的内部 C interface

我们只支持数字(行)索引。

您可以添加一个 "names" 属性并在其中查找索引,and/or 添加您自己的访问器方法。

绝不是一个可靠的解决方案 ,但希望对您来说是一个起点,其中 operator() 被超载以处理 [=12= 的不同组合] 和 string 作为行和列索引传递:

#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]

class MyMat : public Rcpp::NumericMatrix {
  public:
    MyMat(const Rcpp::NumericMatrix& data_,
          const std::vector<std::string>& rnames_,
          const std::vector<std::string>& cnames_)
    : data(data_),
      rnames(rnames_),
      cnames(cnames_) {}

    double operator()(const std::string& i, const std::string& j) {
      typedef std::vector<std::string>::const_iterator cit;
      cit it_i = std::find(rnames.begin(), rnames.end(), i);
      cit it_j = std::find(cnames.begin(), cnames.end(), j);

      int idx_i, idx_j;

      if (it_i != rnames.end() ) {
        idx_i = it_i - rnames.begin();
      } else {
        idx_i = rnames.size();
      }

      if (it_j != cnames.end() ) {
        idx_j = it_j - cnames.begin();
      } else {
        idx_j = cnames.size();
      }

      return data(idx_i, idx_j);
    }

    double operator()(const std::string& i, const size_t j) {
      typedef std::vector<std::string>::const_iterator cit;
      cit it_i = std::find(rnames.begin(), rnames.end(), i);

      int idx_i, idx_j;

      if (it_i != rnames.end() ) {
        idx_i = it_i - rnames.begin();
      } else {
        idx_i = rnames.size();
      }

      if (j <= cnames.size() ) {
        idx_j = j;
      } else {
        idx_j = cnames.size();
      }

      return data(idx_i, idx_j);
    }

    double operator()(const size_t i, const std::string& j) {
      typedef std::vector<std::string>::const_iterator cit;
      cit it_j = std::find(cnames.begin(), cnames.end(), j);

      int idx_i, idx_j;

      if (i <= rnames.size() ) {
        idx_i = i;
      } else {
        idx_i = rnames.size();
      }

      if (it_j != cnames.end() ) {
        idx_j = it_j - cnames.begin();
      } else {
        idx_j = cnames.size();
      }

      return data(idx_i, idx_j);
    }

    double operator()(const int& i, const int& j) {
      return data(i, j);
    }

  private:
    Rcpp::NumericMatrix data;
    std::vector<std::string> rnames;
    std::vector<std::string> cnames;
};

// [[Rcpp::export]]
void test_MyMat(Rcpp::NumericMatrix m)
{
  std::vector<std::string> rnames = { "a", "b", "c" };
  std::vector<std::string> cnames = { "A", "B", "C" };
  MyMat mmObj(m,rnames,cnames);

  Rcpp::Rcout << "(Row 1, Column 1)" <<
    std::endl;
  Rcpp::Rcout << "(b,B) = " << mmObj("b","B") << 
    std::endl << "(b,1) = " << mmObj("b",1) <<
    std::endl << "(1,B) = " << mmObj(1,"B") << 
    std::endl << "(1,1) = " << mmObj(1,1) <<
    std::endl;
}

/*** R
x <- matrix(1:9,nrow=3)

test_MyMat(x)
#(Row 1, Column 1)
#(b,B) = 5
#(b,1) = 5
#(1,B) = 5
#(1,1) = 5

x[2,2]
#[1] 5
*/