Zacznij terazZacznij za darmo

Ś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

Zobacz kurs

Instrukcje do ćwiczenia

  • W warunku if sprawdź, czy i-ty element wektora x jest wartością NA typu NumericVector.
  • 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_na o i-ty element wektora x i dodaj 1 do n_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
  )
*/
Edytuj i uruchom kod