将数字矩阵与 Rcpp 连接起来

Concatenate NumericMatrix with Rcpp

本文关键字:Rcpp 连接 起来 数字      更新时间:2023-10-16

我想使用 Rcpp 折叠转置数字矩阵的行。例如:

library("data.table")   
library("Rcpp")
dt1 <- data.table(V1=c(1, 0, 2),
                  V2=c(1, 1, 0),
                  V3=c(1, 0, 1),
                  V4=c(0, 1, 2),
                  V5=c(1, 1, 1))
cppFunction('NumericMatrix transpose(DataFrame data) {  
             NumericMatrix genotypes = internal::convert_using_rfunction(data, "as.matrix");  
            NumericMatrix tgeno(data.ncol(), data.nrow());  
            int number_samples = data.ncol();    
            int number_snps = data.nrow();    
            for (int i = 0; i < number_snps; i++) {    
              for (int j = 0; j < number_samples; j++) {  
                tgeno(j,i) = genotypes(i,j);  
              }  
            }  
            return tgeno;  
            }')  
dt1  
transpose(dt1)  

原始矩阵

   V1 V2 V3 V4 V5    
1:  1  1  1  0  1    
2:  0  1  0  1  1    
3:  2  0  1  2  1    

转置矩阵

      [,1] [,2] [,3]    
[1,]    1    0    2    
[2,]    1    1    0    
[3,]    1    0    1    
[4,]    0    1    2    
[5,]    1    1    1    

我想要以下矩阵:

      [,1]    
[1,]  102    
[2,]  110    
[3,]  101    
[4,]  012    
[5,]  111     

谁能提出一种方法来做到这一点?

也许作为起点,假设您连接的数字仅由一位数组成:

//' @export
// [[Rcpp::export]]
std::vector<std::string> string_collapse(const Rcpp::DataFrame& data)
{
  R_xlen_t nrow = data.nrow();
  R_xlen_t ncol = data.ncol();
  std::vector<std::string> ret(ncol);
  for (R_xlen_t j = 0; j < ncol; ++j) {
    const auto& col = Rcpp::as<Rcpp::NumericVector>(data[j]);
    std::string ccstr;
    ccstr.reserve(nrow);
    for (const auto& chr: col) {
      ccstr += std::to_string(chr)[0];
    }
    ret[j] = ccstr;
  }
  return ret;
}

它给

dat <- data.frame(V1=c(1, 0, 2),
              V2=c(1, 1, 0),
              V3=c(1, 0, 1),
              V4=c(0, 1, 2),
              V5=c(1, 1, 1))

string_collapse(dat)
[1] "102" "110" "101" "012" "111"

但是,将其与纯R解决方案进行比较的快速基准表明,您不应该期待奇迹。可能仍有优化的余地。

转置矩阵后,您可以按如下方式折叠行:

matrix(apply(dt1, 1, paste0, collapse = ""), ncol = 1)