【问题标题】:Dynamically add rows in Rcpp在 Rcpp 中动态添加行
【发布时间】:2020-04-07 19:59:55
【问题描述】:

我正在尝试在 RcppArmadillo 中编写一个函数,该函数可以动态地将行附加到数组/矩阵中。它应该像 R 中的 rbindPython 中的 pandas.concat 一样工作。 (我依靠 C++ 来提高效率。)

我的具体目标是接收一个名为foo 的向量并生成一个三列矩阵my_matrix,其中每一行都由某些条件确定。因为需要检查每个三元组 {i,j,k} 的条件,所以它涉及一个三元组循环。这是我到目前为止所拥有的(大写字母中的单词是我在这里包含的 cmets):

/* (From my RcppArmadillo script) */
arma::mat myFunction(arma::vec foo) {
  int n = foo.size();
  // initialize first row of column names
  arma::vec my_matrix[] = {"i", "j", "k"}; 
  // loop and append rows
  for(int i = 0; i < n; i++) {
    for(int j = 0; j < n; j++) {
      for(int k = 0; k < n; k++) { 
        if (SOME CONDITION ABOUT i,j,k and foo) {
          APPEND ROW {i,j,k} TO my_matrix 
          arma::vec new_row = {i,j,k};
          my_matrix = join_vert(my_matrix, new_row);
        }
      }
    }
  }
  return my_matrix;
}

我面临三个问题:

  1. arma::vec new_row = {i,j,k}; 行,有人告诉我“在初始化列表中,非常量表达式不能从'int' 类型缩小到'double'
  2. my_matrix = join_vert(my_matrix, new_row); 线上,我被告知“没有匹配函数调用'join_vert'
  3. return my_matrix; 线上,有人告诉我“没有从 'arma::vec [3]' 到 'arma::Mat' 的可行转换(又名 'Mat>')"

因为我不熟悉 C++(尤其是涉及迭代修改的问题 2 和 3)我被卡住了。这里有人可以帮助解决问题吗?提前致谢!

【问题讨论】:

    标签: c++ rcpp rcpparmadillo


    【解决方案1】:

    数据(通常)本机存储为列,因此添加行并不那么明显。因为矩阵通常表示一个连续的向量,所以您需要完整的副本(以创建要填充的“洞”)。

    您最好将不断增长的数据结构表示为列的集合,并让它们单独增长。这几乎就是 data.frame 的作用。

    【讨论】:

      【解决方案2】:

      聆听 Dirk 的最佳实践——按列存储的数据是一个大问题,在编写高效代码时应始终注意这一点。如果由于某种原因你不能听从他的建议,我只是单独写,机械地展示如何完成你描述的事情。

      以下是我将(并且确实)使您的代码工作的方式:

      1. new_row 成为arma::rowvec
      2. my_matrix 成为arma::mat
      3. 在R端设置列名

      现在让我们看看它是什么样子的。在 C++ 方面,我们有:

      #include <RcppArmadillo.h>
      // [[Rcpp::depends(RcppArmadillo)]]
      
      // [[Rcpp::export(.myFunction)]]
      arma::mat myFunction(arma::vec foo) {
          int n = foo.size();
          arma::mat my_matrix;
          // loop and append rows
          for(int i = 0; i < n; i++) {
              for(int j = 0; j < n; j++) {
                  for(int k = 0; k < n; k++) {
                      if ( (foo[i] + foo[j] + foo[k]) > 10.0 ) {
                          arma::rowvec new_row = {i,j,k};
                          my_matrix = arma::join_vert(my_matrix, new_row);
                      }
                  }
              }
          }
          return my_matrix;
      }
      

      然后在R侧:

      myFunction <- function(foo) {
          res <- .myFunction(foo)
          colnames(res) <- c("i", "j", "k")
          return(res)
      }
      

      这是一个实际应用的例子:

      foo <- 1:4
      myFunction(foo)
      
           i j k
      [1,] 2 3 3
      [2,] 3 2 3
      [3,] 3 3 2
      [4,] 3 3 3
      

      顺便说一句,将来我会努力制作更好的可重现示例。 例如,在这里,您没有包含这些行

      #include <RcppArmadillo.h>
      // [[Rcpp::depends(RcppArmadillo)]]
      

      在您的问题代码中。 在这种情况下,这部分是一个小问题,因为很可能任何知道回答您问题的人都知道您需要这些行,但这仍然是不好的做法。

      更重要的是,你不包括

      • ijkfoo 上的条件;
      • 示例函数输入;或
      • 所需的函数输出

      所以,如你所见,我只需要自己编造这些东西。 它可以帮助其他人帮助您提供更好的可重现示例,只是对未来的提示!


      PS:这不可能是解决这个问题的有效方法!

      【讨论】:

        猜你喜欢
        • 2019-11-03
        • 1970-01-01
        • 1970-01-01
        • 2020-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-22
        相关资源
        最近更新 更多