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 :
Le paramètrage na.rm
La fonction na.omit
Le nettoyage croisé des données avec l'écriture !is.na - donner un exemple. (cf. cartographie 2018 de la Dordogne)
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)
}}
}