平均値の繰り上げ(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の条件では、xのi番目の要素がNumericVectorのNAかどうかを確認してください。- 条件が真の場合、結果の
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
)
*/