始める無料で始める

平均値の繰り上げ(Mean carried forward)

最後の観測値の繰り上げ(last observation carried forward)の代わりに、NA をそれまでの非 NA 値の平均で置き換える方法もあります。これは「平均値の繰り上げ(mean carried forward)」と呼ばれます。ここでも、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_meancf1() を C++ に翻訳した na_meancf2() の定義を完成させてください。

この演習はコースの一部です

Rcpp で R コードを最適化する

コースを見る

演習の手順

  • if の条件では、xi 番目の要素が NumericVectorNA かどうかを確認してください。
  • 条件が真の場合、結果の i 番目を、欠損でない値の合計 total_not_na を、欠損でない値の個数 n_not_na で割った値に設定します。
  • それ以外の場合は、total_not_naxi 番目の要素を加え、n_not_na1 を加えてください。

実践的なインタラクティブ演習

このサンプルコードを完成させて、この演習に挑戦してみましょう。

#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
  )
*/
コードを編集して実行