Średnia przenoszona w przód
Alternatywą dla metody przenoszenia ostatniej obserwacji jest zastąpienie wartości NA średnią ze wszystkich poprzednich wartości różnych od NA. Takie podejście nazywa się średnią przenoszoną w przód (ang. mean carried forward). Podobnie jak wcześniej, R zmusza nas do wyboru między czytelnością a szybkością. Poniższy kod napisano z myślą o czytelności:
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
}
Iteracyjna natura tego algorytmu sprawia, że trudno go zwektoryzować – zamiast tego przekształćmy go na kod C++. Uzupełnij definicję funkcji na_meancf2(), będącej tłumaczeniem na_meancf1() na C++.
To ćwiczenie jest częścią kursu
Optymalizacja kodu R za pomocą Rcpp
Instrukcje do ćwiczenia
- W warunku
ifsprawdź, czyi-ty element wektoraxjest wartościąNAtypuNumericVector. - Jeśli warunek jest spełniony, przypisz
i-temu wynikowi iloraz sumy wartości niebraków danych,total_not_na, przez liczbę tych wartości,n_not_na. - W przeciwnym razie zwiększ
total_not_naoi-ty element wektoraxi dodaj1don_not_na.
Interaktywne ćwiczenie praktyczne
Spróbuj tego ćwiczenia, uzupełniając ten przykładowy kod.
#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
)
*/