如何用Rcpp基于sppInSample提取NumericMatrix的指定行列
问题描述
我希望用Rcpp从NumericMatrix中提取指定的行和列,其中dis是一个NumericMatrix,需要基于sppInSample访问它的部分行与列。以下是我的代码片段(非完整代码):
NumericVector mpdCppV2(NumericMatrix samp, NumericMatrix dis, bool abundance_weighted = false) { int N = samp.nrow(); NumericVector mpd(N); Rcout << "The value of v : \n"; for (int i = 0; i < N; ++i) { NumericVector row_i = samp(i, _); CharacterVector sppInSample = as<CharacterVector>(colnames(samp))[row_i > 0]; if (sppInSample.length() > 1) { Rcout << "The value of sppInSample : " << sppInSample << "\n"; NumericMatrix sample_dis = dis(sppInSample, sppInSample); } } return mpd; }
NumericMatrix samp的示例数据:
t4 t5 t9 t8 t1 t2 t3 t10 t7 t6 clump1 1 1 1 1 1 1 1 0 0 1 clump2a 0 0 0 0 0 0 0 1 1 0 clump2b 0 1 1 1 1 0 0 1 1 1 clump4 1 0 1 0 1 0 0 0 0 0 even 0 0 0 1 0 0 0 1 1 1 random 0 1 1 1 0 0 1 0 0 1
NumericMatrix dis的示例数据:
t5 t7 t1 t4 t6 t3 t10 t8 t5 0.0000000 0.8804987 1.323180 1.0106683 2.968295 3.6189006 3.5768501 2.047356 t7 0.8804987 0.0000000 1.285754 0.9732425 3.385655 4.0362613 3.9942108 2.464716 t1 1.3231796 1.2857538 0.000000 1.3278116 3.828336 4.4789422 4.4368917 2.907397 t4 1.0106683 0.9732425 1.327812 0.0000000 3.515825 4.1664308 4.1243803 2.594886 t6 2.9682947 3.3856554 3.828336 3.5158249 0.000000 1.1094981 1.0674476 1.093657 t3 3.6189006 4.0362613 4.478942 4.1664308 1.109498 0.0000000 0.7136734 1.744263 t10 3.5768501 3.9942108 4.436892 4.1243803 1.067448 0.7136734 0.0000000 1.702212 t8 2.0473557 2.4647164 2.907397 2.5948859 1.093657 1.7442627 1.7022122 0.000000 t2 2.8165982 3.2339589 3.676640 3.3641284 2.372962 3.0235676 2.9815171 1.452023 t9 3.2205643 3.6379250 4.080606 3.7680945 2.776928 3.4275338 3.3854833 1.855989 t2 t9 t5 2.816598 3.220564 t7 3.233959 3.637925 t1 3.676640 4.080606 t4 3.364128 3.768095 t6 2.372962 2.776928 t3 3.023568 3.427534 t10 2.981517 3.385483 t8 1.452023 1.855989 t2 0.000000 1.171212 t9 1.171212 0.000000
请问如何正确实现基于sppInSample提取dis矩阵对应行列的功能?
解决方案
Rcpp的NumericMatrix不支持直接用字符向量索引行列,必须先将sppInSample中的物种名转换为dis矩阵对应的行/列索引,再通过整数索引提取子矩阵。
核心步骤
- 获取
dis的列名:由于dis是对称矩阵,行名与列名一致,直接用colnames(dis)获取。 - 物种名转索引:遍历
sppInSample中的每个物种名,在dis的列名中匹配对应的位置(Rcpp中矩阵索引从0开始),将这些索引存入整数向量。 - 提取子矩阵:使用整数索引向量对
dis的行和列进行索引,生成目标子矩阵。
修改后的代码
#include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] NumericVector mpdCppV2(NumericMatrix samp, NumericMatrix dis, bool abundance_weighted = false) { int N = samp.nrow(); NumericVector mpd(N); CharacterVector dis_colnames = colnames(dis); int dis_ncol = dis.ncol(); for (int i = 0; i < N; ++i) { NumericVector row_i = samp(i, _); CharacterVector sppInSample = as<CharacterVector>(colnames(samp))[row_i > 0]; if (sppInSample.length() > 1) { Rcout << "The value of sppInSample : " << sppInSample << "\n"; IntegerVector indices(sppInSample.length()); // 逐个匹配物种名到dis的索引 for (int j = 0; j < sppInSample.length(); ++j) { std::string target_spp = as<std::string>(sppInSample[j]); for (int k = 0; k < dis_ncol; ++k) { if (as<std::string>(dis_colnames[k]) == target_spp) { indices[j] = k; break; } } } // 提取子矩阵 NumericMatrix sample_dis = dis(indices, indices); // 此处可添加对sample_dis的后续计算逻辑 } } return mpd; }
优化方案(大矩阵场景)
如果dis矩阵规模较大,循环匹配物种名效率偏低,可提前建立字符串到索引的哈希映射,后续直接查表匹配:
#include <Rcpp.h> #include <unordered_map> using namespace Rcpp; // [[Rcpp::export]] NumericVector mpdCppV2(NumericMatrix samp, NumericMatrix dis, bool abundance_weighted = false) { int N = samp.nrow(); NumericVector mpd(N); CharacterVector dis_colnames = colnames(dis); int dis_ncol = dis.ncol(); // 提前构建物种名到索引的映射表 std::unordered_map<std::string, int> dis_name_map; for (int k = 0; k < dis_ncol; ++k) { dis_name_map[as<std::string>(dis_colnames[k])] = k; } for (int i = 0; i < N; ++i) { NumericVector row_i = samp(i, _); CharacterVector sppInSample = as<CharacterVector>(colnames(samp))[row_i > 0]; if (sppInSample.length() > 1) { Rcout << "The value of sppInSample : " << sppInSample << "\n"; IntegerVector indices(sppInSample.length()); // 直接查表获取索引 for (int j = 0; j < sppInSample.length(); ++j) { std::string target_spp = as<std::string>(sppInSample[j]); indices[j] = dis_name_map[target_spp]; } NumericMatrix sample_dis = dis(indices, indices); // 后续处理逻辑 } } return mpd; }
内容的提问来源于stack exchange,提问作者Kerby Elpenord
相关产品推荐
相关产品推荐

