Điền giá trị trung bình (mean carried forward)
Một cách khác thay cho phương pháp giữ nguyên quan sát cuối cùng (last observation carried forward) là thay các NA bằng giá trị trung bình của tất cả các giá trị trước đó không phải NA. Cách này gọi là mean carried forward. Một lần nữa, trong R bạn phải chọn giữa khả năng đọc và tốc độ. Đoạn dưới đây ưu tiên khả năng đọc:
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
}
Tính lặp khiến việc vector hóa khá khó, nên thay vào đó, hãy chuyển nó sang C++. Hoàn thiện định nghĩa na_meancf2(), bản C++ của na_meancf1().
Bài tập này là một phần của khóa học
Tối ưu hóa mã R với Rcpp
Hướng dẫn bài tập
- Trong điều kiện
if, kiểm tra xem phần tử thứicủaxcó phải làNAcủaNumericVectorhay không. - Nếu điều kiện đúng, gán kết quả thứ
ibằng tổng các giá trị không khuyếttotal_not_nachia cho số lượng giá trị không khuyếtn_not_na. - Ngược lại, tăng
total_not_nabằng phần tử thứicủax, và cộng1vàon_not_na.
Bài tập tương tác thực hành trực tiếp
Hãy thử làm bài tập này bằng cách hoàn thành đoạn mã mẫu này.
#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
)
*/