Données manquantes, absentes ou vides 

sous R (NA)

L'essentiel de cette page 

Il existe des fonctions utiles pour contrôler la présence de données manquantes sous R is.na() ou na.omit() pour les supprimer.

De nombreuses fonctions contournent les données manquantes avec le paramètre na.rm=T.

Certains packages permettent de visualiser les données manquantes (fonction ci-dessous et package VIM).

D'autres permettent de les remplacer avec pertinence, on fait de l'imputation. Nous pouvons vous y former.

Les types de données manquantes

Il existe plusieurs type de données manquantes, certaines complètement aléatoire comme un oubli de saisi (MCAR) d'autres qui sont liées aux autres variables mais sans impacter la variable (MAR) ou d'autres encore où il n'y a pas de hasard (MNAR).

Si vous souhaitez imputer du MAR ou MCAR, vous pouvez utiliser {MissMDA} : suivez ce lien.

D'autres méthodes permettent de remplacer avec pertinence les NA, on fait de l'imputation. Nous pouvons vous y former.

MCAR, Missing Completly At Random 

Des données manquent du fait du hasard.

On peut les retrouver en regardants les autres variables. Ex : réestimer une taille si on connait l'IMC et le poids d'un individu.

MAR, Missing At Random

Les données manquent au hasard dans une variables sans que cette variable soit impactée et du fait d'autres variables.

Ex : ceux qui habitent loin n'ont pas donné leur poids car ils n'avaient pas le temps car ils voulaient rentrer chez eux.

MNAR, Missing Not At Random

Des données manquent et ce n'est pas le hasard. Cela dépend de la valeur même.

Ex : ceux qui ont un problème avec leur poids (élevé ou trop bas) ne le donnent pas ou alors la balance plante sur les valeurs extrêmes.

EIV, Error In Variable (Imprécision)

Ce n'est pas une donnée manquante en soit, mais il manque une partie de la donnée. 

Ex : je mesure le poids avec une balance précise au kg près. Il faudrait peut-être faire des régressions pour retrouver les dixième de kg qui manquent.

Voir les données manquantes

La fonction matrixplot() de {VIM} permet de voir automatiquement les données manquantes d'une data.frame.

Quand il manque une donnée sous R, R la remplace automatiquement par NA.

Mais comment faire des calculs lorsqu'un NA s'est ainsi glissé dans une liste de valeurs ? Comment s'en affranchir ?

Voici quelques exemples

# Dans le cas où un vecteur contient des indices pour lequel il ne correspond pas de valeurs, on peut afficher toutes les valeurs identifiées de ce vecteur. cf. exemple :

# Voici la liste des poids de 4 de ces 5 personnes, la personne âgée de 72 a refusé de donner son poids.

poids <- c(35, 70, 80, 65, NA)

# Remarque : NA, veut dire que nous ne disposons pas de la valeur.

# Commande pour afficher toutes les valeurs existantes du vecteur poids

poids[!is.na(poids)]

#Pour calculer une moyenne sans tenir compte des valeurs manquantes

mean(poids, na.rm = TRUE)

A développer dans les mises à jour du site  : 

Une fonction pour visualiser les données manquantes par catégories et catégories croisées

Il me manque des données (NA, miss data) : est-ce seulement pour la catégorie fille ou la catégorie garçon. Il y a peut-être un lien ?

Et si j'ai des garçons et filles sportives et d'autres non. Si ça se trouve : seulement des filles qui ne font pas de sport n'ont pas osé donné leur poids parce que leur IMC était socialement gênant.

La fonction boxplot.NA permet de voir cela. (Pour l'utiliser voir-ci-dessous)

Des données simulées à copier-coller dans R pour l'exemple :

reussite <- c(3,3,1,2,3,2,1,3,3,3,NA,2,5,NA,0,rnorm(20,5,3),7,6,3,4,10,NA,3,3,4,5,6,4,3,3,5,6,4,3,3,4,5,3,4,8,6,2) ;length(reussite)

sexe <-  c(NA,"F",rep("F",29),NA,NA,"F",rep("M",15),NA,NA,NA,"M","F","F","F",NA,NA,NA,"M","M");length(sexe)

sport <-  c(NA,"non","oui",rep("non",9),"oui",rep("oui",10),rep("non",7),rep("oui",12),"non",NA,rep("pte",10),"pte","pte",NA,NA,NA,NA,NA);length(sport)

Sans catégorie

boxplot.NA(reussite)

Une liste de catégories

boxplot.NA(reussite,sexe)

Deux listes de catégories à croiser

boxplot.NA(reussite,sexe,sport)

Ci-dessous : le code de la fonction boxplot.NA à copier-coller directement dans R avant de pouvoir l'utiliser (cliquer sur le titre pour afficher)

boxplot.NA <- function(data,cat1=c(), cat2=c()){

  warning <- F

 if (length(cat1)> 0) {

  if (length(cat1)!=length(data)){

   cat("Les vecteurs data et cat1 n'ont pas la même taille !\n")

   warning <- T

  }

  if (length(cat2)> 0) {

   if (length(cat2)!=length(data)){

    cat("Les vecteurs data et cat2 n'ont pas la même taille !\n")

    warning <- T

   }

   if (length(cat2)!=length(cat1)){

    cat("Les vecteurs cat1 et cat2 n'ont pas la même taille !\n")

    warning <- T

   }

  }

 }

 if (warning==F) {

 if (length(cat1)==0) {

  boxplot(data,ylab=deparse(substitute(data)),col="#FEFCD6")

  distance <- max(data,na.rm=T)-summary(data)[2]

  nb_NA <- length(which(is.na(data)))

  #cat("nb_NA",nb_NA,"\n")

  x_NA <- rep(1,nb_NA)

  if (nb_NA==0) {

   cat("Pas de valeurs manquantes.\n")

  } else {

   y_NA <- c()

   for (j in c(1:nb_NA)) {

    y_NA <- c(y_NA,summary(data)[2]+distance/nb_NA*j)

   }

   points(x_NA,y_NA,col="red",pch=16,cex=2)  

   

  }

 } else {

  combinaison <- c() ; as.list(combinaison) ; k<-0 ; designations <- c() ; couleur <- c()

  for (i in sort(unique(cat1))) {

   if (length(cat2)==0) {

    k <- k+1

    data_temp <- data[cat1==i]

    combinaison[[k]] <- data_temp 

    designations <- c(designations,i)

    couleur <- c(couleur,"#FEFCD6")

   } else {

    for (j in sort(unique(cat2))) {

     k <- k+1

     collage <- paste(cat1,cat2)

     data_temp <- data[collage==paste(i,j)]

     #if (length(data_temp)>0){

     combinaison[[k]] <- data_temp 

     designations <- c(designations,paste(i,".",j))

     couleur <- c(couleur,"#FEFCD6")

     #} 

    }

    if (length(data[(cat1==i)&(is.na(cat2))])>0) {

     k <- k+1

     data_temp <- data[(cat1==i)&(is.na(cat2))]

     combinaison[[k]] <- data_temp 

     designations <- c(designations,paste(i,".NA"))

     couleur <- c(couleur,"orange")

    }    

   }

  }

  if (length(cat2)>0) {

   for (j in sort(unique(cat2))) {

    if (length(data[(cat2==j)&(is.na(cat1))])>0) {

     k <- k+1

     data_temp <- data[(cat2==j)&(is.na(cat1))]

     combinaison[[k]] <- data_temp 

     designations <- c(designations,paste("NA.",j))

     couleur <- c(couleur,"orange")

    }


   }

  }

  if ((length(which(is.na(cat1)))>0)&(length(cat2)==0)) {

   k <- k+1

   data_temp <- data[which(is.na(cat1))]

   combinaison[[k]] <- data_temp 

   designations <- c(designations,"NA")

   couleur <- c(couleur,"red")

  } else if (length(which(is.na(cat1)&is.na(cat2)))>0) {

   k <- k+1

   data_temp <- data[which(is.na(cat1)&is.na(cat2))]

   combinaison[[k]] <- data_temp 

   designations <- c(designations,"NA")

   couleur <- c(couleur,"red")

  }

  names(combinaison) <- designations

  boxplot(combinaison,col=couleur,ylab=deparse(substitute(data)))

  #combinaison_NA <- c() ; as.list(combinaison_NA)

  for (m in c(1:length(combinaison))) {

   distance <- max(data,na.rm=T)-summary(data)[2]

   nb_NA <- length(which(is.na(combinaison[[m]])))

   x_NA <- rep(m,nb_NA)   

   if (nb_NA>0) {

    y_NA <- c()

    for (j in c(1:nb_NA)) {

     y_NA <- c(y_NA,summary(data)[2]+distance/nb_NA*j)

    }

    points(x_NA,y_NA,col="red",pch=16,cex=2)  

   }

  }

  return(combinaison)

 }}

}