CommencezCommencez gratuitement

Moyenne reportée

Une autre option que « last observation carried forward » consiste à remplacer les NA par la moyenne de toutes les valeurs précédentes qui ne sont pas NA. On appelle cela la moyenne reportée (mean carried forward). Encore une fois, avec R, il faut choisir entre lisibilité et vitesse. Le code suivant favorise la lisibilité :

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
}

La nature itérative rend la vectorisation difficile. Transformons donc cette fonction en C++. Complétez la définition de na_meancf2(), une traduction C++ de na_meancf1().

Cette activité fait partie du cours

Optimiser le code R avec Rcpp

Voir le cours

Instructions de l’exercice

  • Dans la condition du if, vérifiez si le iᵉ élément de x correspond à un NA d'un NumericVector.
  • Si la condition est vraie, définissez le iᵉ résultat comme le total des valeurs non manquantes, total_not_na, divisé par leur nombre, n_not_na.
  • Sinon, augmentez total_not_na du iᵉ élément de x et ajoutez 1 à n_not_na.

Exercice interactif pratique

Essayez cet exercice en complétant ce code d’exemple.

#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
  )
*/
Modifier et exécuter le code