均值前推(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個元素是否為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
)
*/