矩阵的命名索引
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
*/
我正在尝试用名称索引矩阵。通常的方法报错:
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
*/