rcpp:在移动窗口计算中删除NA

时间:2018-02-27 15:59:18

标签: r rcpp armadillo

我的想法是在移动的窗口中计算几个统计数据(2乘2)。 例如,下面的代码计算移动窗口中的平均值。 当输入数据没有NA值时,它很有效,但是当数据集中有NA时,会产生不良结果(NA被视为最低的int)。 你能指导我如何改进它 - 例如在这些计算中排除NA吗?

#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
Rcpp::NumericMatrix get_mw_mean(arma::imat x){
  int num_r = x.n_rows - 1;
  int num_c = x.n_cols - 1;

  arma::dmat result(num_r, num_c);

  for (int i = 0; i < num_r; i++) {
    for (int j = 0; j < num_c; j++) {
      arma::imat sub_x = x.submat(i, j, i + 1, j + 1);
      arma::ivec sub_x_v = vectorise(sub_x);

      arma::vec sub_x_v2 = arma::conv_to<arma::vec>::from(sub_x_v);
      double sub_mean = arma::mean(sub_x_v2);
      result(i, j) = sub_mean;
    }
  }
  return(wrap(result));
}

/*** R
new_c1 = c(1, 86, 98,
           15, 5, 85,
           32, 25, 68)
lg1 = matrix(new_c1, nrow = 3, byrow = TRUE)
get_mw_mean(lg1)
new_c2 = c(NA, 86, 98,
           15, NA, 85,
           32, 25, 68)
lg2 = matrix(new_c2, nrow = 3, byrow = TRUE)
get_mw_mean(lg2)
*/

干杯, 小额

1 个答案:

答案 0 :(得分:4)

这里发生了两件事:

  1. 矩阵输入类型arma::imat已签名 int,但NANaN仅出现在{ {1}}或float类型。从本质上讲,double不能设计intNA占位符。因此,发生的转换是降至NaN

  2. 需要为INT_MIN C ++ 中的NANaN值进行子集化。

  3. 因此,前进的方法是选择检测此int值并将其从矩阵中删除。实现此目的的一种方法是使用find()来标识与INT_MIN.elem()不匹配的有限元素,以提取已标识的元素。

    涉及INT_MIN的案件,例如double / arma::mat /等等,请考虑使用find_finite()

    实施

    arma::vec

    输出

    #include <RcppArmadillo.h>
    
    // [[Rcpp::depends(RcppArmadillo)]]
    
    // [[Rcpp::export]]
    arma::mat get_mw_mean_na(arma::imat x){
      int num_r = x.n_rows - 1;
      int num_c = x.n_cols - 1;
    
      Rcpp::Rcout << x <<std::endl;
    
      arma::dmat result(num_r, num_c);
    
      for (int i = 0; i < num_r; i++) {
        for (int j = 0; j < num_c; j++) {
          arma::imat sub_x = x.submat(i, j, i + 1, j + 1);
          // Conversion + Search for NA values
          arma::vec sub_x_v2 = arma::conv_to<arma::vec>::from( 
                                            sub_x.elem( find(sub_x != INT_MIN) ) 
          );
    
          result(i, j) = arma::mean(sub_x_v2);
        }
      }
    
      return result;
    }