-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmissing_data.Rmd
214 lines (157 loc) · 9.85 KB
/
missing_data.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# Données manquantes {#missing}
![](images/banners/banner_missing.png)
*Ce chapitre a été réalisé dans le cadre d'une collaboration communautaire créée par [ujjwal95](https://github.com/ujjwal95){target="_blank"}*
*Cette page est en cours de réalisation. Nous apprécions tout commentaire ou feedback. Si vous voulez participez et nous aider à améliorer cette page, vous pouvez [contribuer à notre repo](contribute.html).*
## Vue d'ensemble
Dans cette section, nous verrons plusieurs types de données manquantes et la façon de les traiter.
## tl;dr
Il peut être difficile de traiter des données manquantes! S'il manque des données dans nos datasets, ce qui est très souvent le cas, on peut soit s'en débarrasser, soit en déduire la valeur.
## Que sont les NAs?
Lorsqu'une donnée dans un rang ou colonne est manquante, elle apparaitra sous de la forme NA. Regardons ça d'un peu plus près:
```{r echo = FALSE, message=FALSE}
library(tidyverse)
library(scales)
Name <- c("Melissa", "Peter", "Aang", "Drake", "Bruce", "Gwen", "Ash",NA)
Sex <- c("Female", NA, "Male", "Male", NA, "Female", "Male",NA)
Age <- c(27, NA, 110, NA, 45, 28, NA, NA)
E_mail <- c(NA, "[email protected]", "[email protected]", NA, "[email protected]", "[email protected]", "[email protected]", NA)
Education <- c(NA, NA, NA, NA, NA, NA, NA, NA)
Income <- c(10000, 7500, 1000, 50000, 10000000, 23000, NA, NA)
data <- data.frame(Name, Sex, Age, E_mail, Education, Income)
```
```{r echo = FALSE}
library(knitr)
kable(data)
```
On peut aussi voir le nombre de NAs dans chaque rang et colonne.
```{r}
colSums(is.na(data))
```
```{r}
rowSums(is.na(data))
```
On peut aussi calculer le ratio du nombre de NAs dans chaque rang et colonne:
```{r}
colMeans(is.na(data))
```
```{r}
rowMeans(is.na(data))
```
## Types de Données Manquantes
- **Missing Completely at Random (MCAR)**: Ce sont des valeurs manquantes qui ne sont pas liées à d'autres valeurs, manquantes ou non, du dataset.
- **Missing at Random (MAR)**: Ce sont des valeurs manquantes qui sont liées à un ou plusieurs autres groupes de données dans le dataset. La bonne nouvelle avec les valeurs manquantes de ce type-là, c'est qu'elles peuvent être déduites (et prédites) par d'autres données présentes dans le dataset. Par exemple, on peut observer que des personnes de plus de 70 ans ont tendance à ne pas donner d'informations sur leur salaire. La plupart des données manquantes à traiter dans la vraie vue sont de ce type-là.
- **Missing Not at Random (MNAR)**: En général, une donnée manquante qui n'est pas MAR est MNAR. Le problème est cependant qu'il n'y a pas de grande distinction entre les deux. On supposera donc que la donnée manquante est de type MAR à moins que le contraire soit précisé et confirmé par une source extérieure.
## Patterns manquants
### Patterns manquants par colonne
On peut voir certains patterns manquants dans les données par colonne,
```{r echo = FALSE, warning=FALSE}
tidy_names <- data %>%
gather(key, value, -Name) %>%
mutate(missing = ifelse(is.na(value), "yes", "no"))
```
```{r}
ggplot(tidy_names, aes(x = key, y = fct_rev(Name), fill = missing)) +
geom_tile(color = "white") +
ggtitle("Names dataset with NAs added") +
scale_fill_viridis_d() +
theme_bw()
```
Et on peut aussi ajouter une échelle de valeur pour vérifier les valeurs numériques disponibles dans le dataset et tenter de trouver des tendances:
```{r message=FALSE}
library(scales) # for legend
# Select columns having numeric values
numeric_col_names <- colnames(select_if(data, is.numeric))
filtered_for_numeric <- tidy_names[tidy_names$key %in% numeric_col_names,]
filtered_for_numeric$value <- as.integer(filtered_for_numeric$value)
# Use label=comma to remove scientific notation
ggplot(data = filtered_for_numeric, aes(x = key, y = fct_rev(Name), fill = value)) +
geom_tile(color = "white") +
scale_fill_gradient(low = "grey80", high = "red", na.value = "black", label=comma) +
theme_bw()
```
Est-ce que vous pouvez voir le problème avec le graphe ci-dessus? Avez-vous vu que l'échelle est pour *toutes* les valeurs, et que donc on ne peut pas voir les différences de niveau entre variables?
Pour résoudre ce problème, on peut standardiser les variables:
```{r}
filtered_for_numeric <- filtered_for_numeric %>%
group_by(key) %>%
mutate(Std = (value-mean(value, na.rm = TRUE))/sd(value, na.rm = TRUE)) %>%
ungroup()
ggplot(filtered_for_numeric, aes(x = key, y = fct_rev(Name), fill = Std)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "blue", mid = "white", high ="yellow", na.value = "black") + theme_bw()
```
Maintenant, on peut mieux voir les patterns manquants! Trions-les selon le nombre manquant pour chaque rang et colonne:
```{r}
# convert missing to numeric so it can be summed up
filtered_for_numeric <- filtered_for_numeric %>%
mutate(missing2 = ifelse(missing == "yes", 1, 0))
ggplot(filtered_for_numeric, aes(x = fct_reorder(key, -missing2, sum), y = fct_reorder(Name, -missing2, sum), fill = Std)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "blue", mid = "white", high ="yellow", na.value = "black") + theme_bw()
```
### Patterns manquants par rang
On peut aussi voir les patterns manquants dans le dataset par rang en utilisant le package `mi`:
```{r message=FALSE}
library(mi)
x <- missing_data.frame(data)
image(x)
```
Avez-vous remarqué que la variable `Education` n'a pas été prise en compte? C'est parce que toute la colonne est manquante.
Essayons maintenant de trouver des patterns dans les données manquantes:
```{r}
x@patterns
```
```{r}
levels(x@patterns)
```
```{r}
summary(x@patterns)
```
On peut visualiser les patterns manquants en utilisant la fonction `visna` (VISualize NA) dans le package `extracat`:
```{r}
extracat::visna(data)
```
Ici, les rangs représentent un pattern manquant et les colonnes représentent le niveau de la colonne dans laquelle les valeurs sont manquantes. L'avantage de ce graph est qu'il montre seulement les patterns manquants qui sont disponibles dans les données et pas toutes les combinaisons possibles de données (ce qui reviendrait à 2^6 = 64), et on peut donc se concentrer sur le pattern dans les données elles-mêmes.
We can sort the graph by most to least common missing pattern (i.e., by row):
On peut réarranger le graphe du pattern manquant le plus commun au moins commun.
```{r}
extracat::visna(data, sort = "r")
```
Ou du plus au moins de valeurs manquantes (ex: par colonne):
```{r}
extracat::visna(data, sort = "c")
```
Ou on peut également trier par rang et colonne:
```{r}
extracat::visna(data, sort = "b")
```
## Traiter les valeurs manquantes
il y a plusieurs méthodes pour traiter les valeurs manquantes
### Supression des rangs comprenant des NAs
Souvent, on supprimera les rangs qui contiennent des NAs lorsqu'on fait face à des données MCR.
On peut procéder de la façon suivante:
```{r}
na.omit(data)
```
Cette méthode est appelée *list-wise deletion*. Elle supprime tous les rangs avec des NAs. Mais comme on peut voir que la colonne 'Education' ne contient que des NAs, on peut supprimer toute la colonne:
```{r}
edu_data <- data[, !(colnames(data) %in% c("Education"))]
na.omit(edu_data)
```
On peut également parler d'une autre méthode appelée *pair-wise deletion*, avec laquelle seulement les rangs qui possèdent des valeurs manquantes dans la variable d'intérêt seront supprimés.
### Technique de prédiction
Imputation means to replace missing data with substituted values. These techniques are generally used with MAR data.
Une autre possibilité est de remplacer les valeurs manquantes par des valeurs de substitution. Ces techniques sont généralement utilisées avec des données MAR.
#### Substition par la Moyenne/Médiane/Mode
On peut remplacer les valeurs manquantes pour des variables continues par leur moyenne ou médiane et les valeurs manquantes pour des variables discrètes ou catégorielles par leur mode.
Soit on remplace toutes les valeurs de la variable manquante directement (par exemple, si 'Income' a une médiane de 15000, on remplace toutes les variables manquantes de "Income" par 15000) grâce à une technique qu'on appelle *Generalized Imputation*.
Soit on remplace toutes les valeurs sur base de cas similaires. Par exemple, si on remarque les personnes avec `Age > 60` ont un salaire beaucoup plus bas que ceux avec `Age < 60` en moyenne, on va calculer le salaire médian pour chaque groupe d'`Age` séparément.
Le problème avec ces méthodes cependant est qu'elles perturbent la distribution sous-jacente de nos données.
### Prédiction par modèle
Il existe plusieurs modèles pour tenter de prédire les données manquantes ainsi que plusieurs packages comme [mice](https://cran.r-project.org/web/packages/mice/index.html){target="_blank"}, [Hmisc](https://cran.r-project.org/web/packages/Hmisc/index.html){target="_blank"}, et [Amelia II](https://cran.r-project.org/web/packages/Amelia/index.html){target="_blank"}.
Pour plus d'info, veuillez lire [ce blog sur DataScience+ sur la prédiction de données manquantes avec le package mice en R](https://datascienceplus.com/imputing-missing-data-with-r-mice-package/){target="_blank"}.
## External Resources
- [Missing Data Imputation](http://www.stat.columbia.edu/~gelman/arm/missing.pdf){target="_blank"} - A PDF by the Stats Department at Columbia University regarding Missing-data Imputation
- [How to deal with missing data in R](https://datascienceplus.com/missing-values-in-r/){target="_blank"} - A 2 min read blogpost in missing data handling in R
- [Imputing Missing Data in R; MICE package](https://datascienceplus.com/imputing-missing-data-with-r-mice-package/){target="_blank"} - A 9 min read on how to use the `mice` package to impute missing values in R
- [How to Handle Missing Data](https://towardsdatascience.com/how-to-handle-missing-data-8646b18db0d4){target="_blank"} - A great blogpost on how to handle missing data.