開始使用免費開始

均值前推(Mean Carried Forward)

與「最後觀測值前推」相對的做法,是把 NA 以前面所有非 NA 值的平均數來取代。這種方法稱為「均值前推」。同樣地,在 R 中常需要在可讀性與速度之間取捨。以下程式碼為了可讀性而撰寫:

na_meancf1 <- function(x) {
  total_not_na <- 0
  n_not_na <- 0
  res <- x
  for(i in seq_along(x)) {
    if(is.na(x[i])) {
      res[i] <- total_not_na / n_not_na
    } else {
      total_not_na <- total_not_na + x[i]
      n_not_na <- n_not_na + 1
    }
  }
  res
}

由於這個演算法是逐步累計,向量化不太容易,因此我們改以 C++ 實作。請完成 na_meancf2() 的定義,這是 na_meancf1() 的 C++ 翻譯版本。

本練習屬於課程

用 Rcpp 最佳化 R 程式碼

檢視課程

練習說明

  • if 條件中,檢查 x 的第 i 個元素是否為 NumericVectorNA
  • 若條件成立,將第 i 個結果設為非缺值總和 total_not_na 除以非缺值個數 n_not_na
  • 否則,將 total_not_na 增加 x 的第 i 個元素,並將 n_not_na 加上 1

動手互動練習

試著完成這個範例程式碼,體驗一下這個練習。

#include 
using namespace Rcpp; 

// [[Rcpp::export]]
NumericVector na_meancf2(NumericVector x) {
  double total_not_na = 0.0;
  double n_not_na = 0.0;
  NumericVector res = clone(x);
  
  int n = x.size();
  for(int i = 0; i < n; i++) {
    // If ith value of x is NA
    if(___) {
      // Set the ith result to the total of non-missing values 
      // divided by the number of non-missing values
      res[i] = ___ / ___;
    } else {
      // Add the ith value of x to the total of non-missing values
      ___;
      // Add 1 to the number of non-missing values
      ___;
    }
  }  
  return res;
}

/*** R
  library(microbenchmark)
  set.seed(42)
  x <- rnorm(1e5)
  x[sample(1e5, 100)] <- NA  
  microbenchmark( 
    na_meancf1(x), 
    na_meancf2(x), 
    times = 5
  )
*/
編輯並執行程式碼