均值向前填充
与"前一个观测值填充"(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_meancf2() 的定义,它是 na_meancf1() 的 C++ 版本。
本练习是课程的一部分
用 Rcpp 优化 R 代码
练习说明
- 在
if条件中,检查x的第i个元素是否为NumericVector的NA。 - 如果条件为真,将第
i个结果设为非缺失值总和total_not_na除以非缺失值个数n_not_na。 - 否则,将
x的第i个元素加到total_not_na上,并将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
)
*/