Analyses exploratoires avec le package DataExplorer

Assez récemment, au cours d’une séance de coaching, une des mes clientes m’a montré des analyses exploratoires de son jeu de données, qu’elle avait réalisé avec le package DataExplorer. Comme les analyses étaient intéressantes et que ce n’était pas la première fois que j’entendais parler de ce package, j’ai décidé de le “décortiquer”.

Dans cet article, je vous montre, en pas à pas, les fonctions qui ont retenu mon attention. Et en guise de conclusion, je vous donnerai mon avis global sur ce package DataExplorer.

Table des matières

C’est quoi les analyses exploratoires ?

Les analyses exploratoires – ou EDA en anglais pour Explanatory Data Analysis- servent à faire un état des lieux des données : Quelles sont les dimensions (nombre de lignes, nombre de colonnes) du data frame ? Quel est le pourcentage de données manquantes, où sont elles ? Quelles sont les variables quantitatives et quelles sont les variables qualitatives. Quelles sont les distributions des variables ? Quelles sont, grossièrement, les relations entre les variables ? Etc…

Je dirais que les analyses exploratoires interviennent immédiatement après le nettoyage des données, et juste avant les analyses descriptives, qui sont plus précises que les analyses exploratoires, et qui vont s’intéresser plus particulièrement à certaines variables.

Le package DataExplorer

Ce package est disponible sur CRAN, il est donc facile à installer à partir de RStudio:

#install.packages("DataExplorer")
library("DataExplorer") 

La promesse de DataExplorer c’est d’automatiser l’exploration des variables (dimension, données manquantes, distribution, corrélation etc) d’un data frame, pour nous permettre de nous concentrer sur la compréhension des données.

Sur le principe, c’est super intéressant, parce que l’exploration des données c’est chronophage, et on ne peut pas trop s’en passer pour bien comprendre le jeu de données !

DataExplorer contient une vingtaine de fonctions. Je les ai essayé de manière systématique, les une après les autres, en employant le jeu de données heart_disease du package funModeling parce que je le connais bien (et vous aussi si vous suivez mes articles ) 😉

#install.packages("funModeling")
library("funModeling")
 

Vous trouverez la liste des fonctions du package ici. Et des exemples d’utilisation, là.

Dans cet article, je ne vais pas vous présenter toutes les fonctions, mais seulement que j’ai trouvé intéressantes. J’ai essayé de les rassembler par thématique, ou étape de l’analyse exploratoire.

Analyses exploratoires de la structure des données

Pour cette première étape, trois fonctions ont retenu mon attention, introduce(), plot_intro() et plot_str(). Elles permettent toutes les trois d’obtenir des informations sur la structure de données, c’est-à-dire leurs dimensions, les class (ou types de variables), la présence de données manquantes, etc.

La fonction introduce()

introduce(heart_disease)
##   rows columns discrete_columns continuous_columns all_missing_columns
## 1  303      16                7                  9                   0
##   total_missing_values complete_rows total_observations memory_usage
## 1                    6           297               4848        28800 

La fonction plot_intro()

Cette fonction permet d’obtenir les mêmes informations, mais sous la forme d’un graphique : 

plot_intro(heart_disease) 
Class des variable avec DataExplorer

La fonction plot_str()

Cette fonction permet d’aller dans le détail de chaque variable et d’obtenir un résultat synthétique, sous la forme d’un graphique (au format html).

Exploration de la structure des données

Modification des class

Suite à l’exploration de la structure des données, il est parfois nécessaire de modifier la class de certaines variables. Par exemple, pour passer une variable de type chaîne de caractères vers une variable de type factor, ou inversement.

Le package DataExplorer dispose d’une fonction très utile pour cela, la fonction update_columns. Cette fonction permet de modifier le type d’une ou plusieurs variables en une seule ligne de commande, en utilisant les noms ou les indices (position de la variable).

Par exemple, la variable age est de class integer. Si je voulais le changer en chaîne de caractères (character) :

# copie de heart_disease
HD <- heart_disease
class(heart_disease$age) #integer
## [1] "integer"
HD <- update_columns(HD, "age", as.character)
class(HD$age)# character
## [1] "character" 

Un autre exemple, avec plusieurs variables :

class(HD$resting_blood_pressure) #integer
## [1] "integer"
class(HD$serum_cholestoral) #integer
## [1] "integer"
# avec plusieurs variables, en utilisant les noms
HD <- update_columns(HD, c("resting_blood_pressure","serum_cholestoral"), as.numeric)
class(HD$resting_blood_pressure) #numeric
## [1] "numeric"
class(HD$serum_cholestoral) #numeric
## [1] "numeric" 

Idem, en utilisant des indices :

str(HD[,2:5])
## 'data.frame':    303 obs. of  4 variables:
##  $ gender                : Factor w/ 2 levels "female","male": 2 2 2 2 1 2 1 1 2 2 ...
##  $ chest_pain            : Factor w/ 4 levels "1","2","3","4": 1 4 4 3 2 2 4 4 4 4 ...
##  $ resting_blood_pressure: num  145 160 120 130 130 120 140 120 130 140 ...
##  $ serum_cholestoral     : num  233 286 229 250 204 236 268 354 254 203 ...
HD <- update_columns(heart_disease, 2:5, as.character)
str(HD[,2:5])
## 'data.frame':    303 obs. of  4 variables:
##  $ gender                : chr  "male" "male" "male" "male" ...
##  $ chest_pain            : chr  "1" "4" "4" "3" ...
##  $ resting_blood_pressure: chr  "145" "160" "120" "130" ...
##  $ serum_cholestoral     : chr  "233" "286" "229" "250" ... 

Analyses exploratoires des données manquantes

Les données manquantes c’est toujours embêtant, à minima parce que, par défaut, R ne les gère pas. Il faut souvent utiliser l’argument na.rm=TRUE dans les fonctions descriptives, par exemple. Et puis aussi parce que certaines approches statistiques ne les tolèrent pas, comme l’ACP par exemple. C’est donc bien de réaliser une exploration des données manquantes pour se faire une idée de leur nombre et de leur répartition.

Pour cela le package propose deux fonctions : plot_missing() et profiling_missing().

La fonction plot_missing()

Cette fonction permet d’obtenir, sous la forme d’un graphique, le pourcentage de données manquante pour chaque variables. C’est plutôt simple et efficace :

plot_missing(heart_disease) 
Exploration des données manquantes

Remarque : pour aller plus loin dans l’exploration visuelle de la distribution des données manquantes, vous pouvez aussi consulter cet article  “Visualisation des données manquantes“, et aussi employer la fonction aggr() du package VIM

La fonction profiling_missing()

La fonction profiling_missing() permet d’obtenir les pourcentages et les effectifs correspondants de données manquantes, mais sous la forme d’un data frame:

profile_missing(heart_disease)
##                   feature num_missing pct_missing
## 1                     age           0  0.00000000
## 2                  gender           0  0.00000000
## 3              chest_pain           0  0.00000000
## 4  resting_blood_pressure           0  0.00000000
## 5       serum_cholestoral           0  0.00000000
## 6     fasting_blood_sugar           0  0.00000000
## 7         resting_electro           0  0.00000000
## 8          max_heart_rate           0  0.00000000
## 9             exer_angina           0  0.00000000
## 10                oldpeak           0  0.00000000
## 11                  slope           0  0.00000000
## 12      num_vessels_flour           4  0.01320132
## 13                   thal           2  0.00660066
## 14 heart_disease_severity           0  0.00000000
## 15           exter_angina           0  0.00000000
## 16      has_heart_disease           0  0.00000000 

Analyses exploratoires la distribution des variables

Après l’étude de la structure et des données manquantes, on peut s’intéresser à la distribution des variables. Les graphiques permettent une synthèse optimale de l’information.

Variables qualitatives

Pour explorer les variables qualitatives, le package DataExplorer propose la fonction plot_bar().

Les distributions peuvent être obtenues de façon globale, ou par sous-groupes:

# global
plot_bar(heart_disease) 
Exploration de la distribution des variables qualitatives
# par sous-groupes
plot_bar(heart_disease, by ="gender") 
exploration de la distribution des variables qualitatives par sous groupes avec DataExplorer

Les graphs peuvent être améliorés, vous trouverez plus d’information dans la page d’aide des fonctions. Par exemple :

?plot_bar() 

variables quantitatives

De façon analogue, pour les variables quantitatives, le package propose les fonctions plot_histogram() et plot_qq(). Ces fonctions sont plutôt pratiques pour visualiser les distributions et se faire une première idée quant à la normalité ou non des variables :

plot_histogram(heart_disease) 
analyse exploratoire des variables quantitatives
plot_qq(heart_disease) 
analyses exploratoire des variables quantitatives avec des qqplot

Les qqplot peuvent être obtenus en distinguant des sous-groupes :

plot_qq(heart_disease, by="chest_pain") 
 
Analyses exploratoires des variables quantitatives par qqplot

Exploration des relations entre les variables

Les relations entre les variables peuvent également être explorées à l’aide de graphiques, générés notamment par les fonctions plot_correlation()plot_prcomp()plot_boxplot() et plot_scatterplot()

Analyses exploratoires des corrélations

La fonction plot_correlation

La fonction plot_correlation permet d’obtenir une matrice de corrélation visuelle pour l’ensemble des variables (quantitatives ou qualitatives). Obtenir une matrice de corrélation sur des variables qualitatives peut paraître un peu surprenant… Pour cela des variables indicatrices, ou “dummy” variables (comportant des 0 et des 1) sont créées et les corrélations sont calculées à partir de ces données numériques.

Le package comporte d’ailleurs une fonction (dummify() – très intéressante !) pour créer ces dummy variables. Mais ici la fonction plot_correlation le fait de toute seule.

plot_correlation(heart_disease, cor_args = list("use" = "pairwise.complete.obs")) 

On peut aussi obtenir une matrice des corrélations, uniquement pour les variables qualitatives et uniquement avec les variables quantitatives. Pour cela, on ajoute l’argument type="d" pour les données discrètes (catégorielles) et type="c" pour les données continues (quantitatives)

plot_correlation(heart_disease, cor_args = list("use" = "pairwise.complete.obs"), type="d") 
analyses exploratoires des corrélations des variables qualitatives
plot_correlation(heart_disease, cor_args = list("use" = "pairwise.complete.obs"), type="c") 
analyses exploratoires des correlations de variables quantitatives

Remarque : Pour obtenir des informations complémentaires sur les matrices de corrélation, vous pouvez consulter cet article “Correlations deux à deux”.

La fonction plot_prcomp()

Les corrélations peuvent aussi s’apprécier par les sorties de la fonction plot_prcomp(), qui réalise une ACP (analyse en composantes principale). Les infos sur les pourcentages d’inertie nous permettent d’apprécier sur combien de dimensions les données peuvent être réduites.

plot_prcomp(na.omit(heart_disease), nrow = 2L, ncol = 2L) 
POurcentage d'inerties des composantes principales

Remarques : vous pourrez trouver davantage  d’informations sur l’approche ACP dans l’article “Ressources pour l’ACP“.

 

Laisons entre une variable qualitative et les variables quantitatives

La fonction plot_boxplot() permet de visualiser ces relations en créant des boxplots pour toutes les variables numériques, en une seule ligne de commande. La variable catégorielle est spécifiée à l’aide de l’argument by.

plot_boxplot(heart_disease, by="gender") 
Réalisation automatisée de boxplots avec la fonction plot_boxplot

Les boxplots sont simples (les observations ne sont superposées) mais pour de l’exploration cela me semble suffisant.

 

Liaisons entre une variable quantitative spécifique et les autres variables quantitatives.

Pour cela, nous pouvons employer la fonction plot_scatterplot(), mais il est nécessaire, soit en amont, soit dans la fonction, de sélectionner uniquement les variables quantitatives (ici dans la fonction, avec la commande split_columns(heart_disease)$continuous ).

plot_scatterplot(split_columns(heart_disease)$continuous, by = "max_heart_rate") 
Réalisation automatisée de scatterplots avec le package DataExplorer

Il est même possible de réaliser un échantillonnage lorsque les données sont très nombreuses, en utilisant l’argument sampled_rows.

 

Création de dummy variables

Lepackage DataExplorer propose la fonction dummify() pour créer des variables indicatrices (ou dummy variables) à partir d’une variable catégorielle. Voici un exemple :

library(tidyverse)
# subset avec 3 variables catégorielle
HD_simple <- heart_disease %>% 
  select(gender, chest_pain, has_heart_disease) 
str(HD_simple)
## 'data.frame':    303 obs. of  3 variables:
##  $ gender           : Factor w/ 2 levels "female","male": 2 2 2 2 1 2 1 1 2 2 ...
##  $ chest_pain       : Factor w/ 4 levels "1","2","3","4": 1 4 4 3 2 2 4 4 4 4 ...
##  $ has_heart_disease: Factor w/ 2 levels "no","yes": 1 2 2 1 1 1 2 1 2 2 ...
HD_simple2 <- dummify(HD_simple) 
str(HD_simple2)
## 'data.frame':    303 obs. of  8 variables:
##  $ gender_female        : int  0 0 0 0 1 0 1 1 0 0 ...
##  $ gender_male          : int  1 1 1 1 0 1 0 0 1 1 ...
##  $ chest_pain_1         : int  1 0 0 0 0 0 0 0 0 0 ...
##  $ chest_pain_2         : int  0 0 0 0 1 1 0 0 0 0 ...
##  $ chest_pain_3         : int  0 0 0 1 0 0 0 0 0 0 ...
##  $ chest_pain_4         : int  0 1 1 0 0 0 1 1 1 1 ...
##  $ has_heart_disease_no : int  1 0 0 1 1 1 0 1 0 0 ...
##  $ has_heart_disease_yes: int  0 1 1 0 0 0 1 0 1 1 ...
##  - attr(*, ".internal.selfref")=<externalptr> 

Rapport automatisé des analyses exploratoires

Bon ben ça, c’est pas la cerise sur le gâteau, c’est le gâteau tout entier !

Toutes les fonctions que l’on vient de voir (et d’autres), peuvent être appliquées automatiquement sur votre jeu de données, avec une seule ligne de commande. Et vous pouvez obtenir les résultats dans un fichier html, tout beau tout propre ! Ca paraît trop beau ? C’est pourtant vrai. La fonction à employer est create_repor(), comme cela :

create_report(heart_disease) 
Rapport d'analyses exploratoires

Vous pouvez choisir les analyses réalisées dans ce rapport, en employant la fonction configure_report.

configure_report(
  add_introduce = TRUE,
  add_plot_intro = TRUE,
  add_plot_str = TRUE,
  add_plot_missing = TRUE,
  add_plot_histogram = TRUE,
  add_plot_density = FALSE,
  add_plot_qq = TRUE,
  add_plot_bar = TRUE,
  add_plot_correlation = TRUE,
  add_plot_prcomp = TRUE,
  add_plot_boxplot = TRUE,
  add_plot_scatterplot = TRUE,
  introduce_args = list(),
  plot_intro_args = list(),
  plot_str_args = list(type = "diagonal", fontSize = 35, width = 1000, margin =
    list(left = 350, right = 250)),
  plot_missing_args = list(),
  plot_histogram_args = list(),
  plot_density_args = list(),
  plot_qq_args = list(sampled_rows = 1000L),
  plot_bar_args = list(),
  plot_correlation_args = list(cor_args = list(use = "pairwise.complete.obs")),
  plot_prcomp_args = list(),
  plot_boxplot_args = list(),
  plot_scatterplot_args = list(sampled_rows = 1000L),
  global_ggtheme = quote(theme_gray()),
  global_theme_config = list()
) 

En principe, il doit être possible de générer le rapport en docx ou .pdf, mais je ne suis pas parvenue à changer le format de sortie par défaut (html).

Conclusion

Après cette exploration du package, je suis plutôt séduite. Non seulement le package facilite la réalisation des analyses exploratoires, mais il les rend aussi très intelligibles par l’emploi de graphiques, et surtout il les automatise !

Et ça, c’est un gain de temps considérable. Et puis le package est très facile d’utilisation. 

En rentant davantage dans le détail des fonctions, j’ai bien apprécié les fonctions la réalisation de matrice de corrélation avec les variables catégorielles, et la restitution très simple de l’ACP.

Cette étude du package DataExplorer me donne envie de décortiquer d’autres packages dédiés à l’exploration des données. 

J’aimerais bien, ensuite, faire un récapitulatif pour décrire quelle fonction de quel package permet de faire facilement telle ou telle étape de l’analyse exploratoire. Est-ce que ça vous intéresse ? Dites-le-moi en commentaire !

Et si vous souhaitez me suggérer des packages à étudier n’hésitez pas non plus !

Si cet article vous a plu, ou vous a été utile vous pouvez soutenir le blog, en réalisant un don libre sur sa page Tipeee.

Poursuivez votre lecture

29 Responses

  1. Bonjour !
    Merci pour cet article très clair ( comme d’habitude 🙂 ) sur ce package que je ne connaissais pas.
    Votre proposition d’approfondir sur les analyses exploratoires est intéressante !
    Bonne journée !

  2. Merci beaucoup pour ce partage! Votre blog est toujours une mine d’informations précieuses.
    L’idée d’une compilation des packages dediés à l’exploration des données est top. J’attends cet article avec impatience

  3. Hello bonjour,
    Personnellement je commence en Data analyse et je dois admettre avoir un penchant pour R. Cet article est très intéressant et je vous en remercie. Effectivement je vais tenter d’utiliser ce package dans un projet de ma formation pour essayer de mettre en évidence des corrélations.
    Grand Merci dans tous les cas car ce fut une belle surprise de voir ce mail d’info aujourd’hui ! C’est un peu Noël presque tous les jours avec Della data !
    Bonne semaine !
    L.

  4. Dear Della,

    Cet article m’a beaucoup plus et vient de repondre à une de mes préoccupations surtout sur les corrélations avec les variables catégorielles et bien d’autres aussi. Merci beaucoup

  5. Salut !

    Merci pour cet excellent article et surtout pour ce package trèèèès intéressant. Je m’en vais l’essayer tout de suite !
    En revanche, je n’ai pas bien compris la fonction plot_str()…. A quoi sert-elle exactement ?

    1. Elle fournit un plot avec une description de la structure des données. C’est l’équivalent de la fonction str, mais sous une forme graphique.

  6. Très respectueusement , je vous fournis les arguments principaux qui me font critiquer très négativement l’outil proposé dans le cadre où vous le présentez
    .
    1) Notre cerveau est ainsi conçu qu’il recherche la facilité , ce qui est utile pour un mammifère en milieu hostile mais pas dans la recherche;
    la conséquence en est qu’il se laisse fasciner par la première forme qu’il reconnaît dans son catalogue d’expériences : il va développer une cécité spécifique à tout autre signe qui mettrait en péril la valeur de cette forme identifiée.
    Ne perdons pas de vue le stress lié à toute recherche qui en rajoute une couche.

    2) Le paradigme de toutes les recherches du XXI ème siècle est essentiellement basé sur la complexité , et nous savons que l’identification d’une “Solution magique ???” amènerait immédiatement à une simplification catastrophique des raisonnements et surtout de nos représentations.

    3) Le plus mauvais moment pour le parasitage de la démarche est vraiment au début de la recherche ; en effet c’est le moment pour douter de tout et de ses “contraires” : c’est le moment de s’ouvrir à la réalité et de s’interdire toute conclusion hâtive , c’est le moment du rêve éveillé.

    4) Le calcul n’est jamais qu’un calcul , quelle que soit l’élégance de sa ou ses forme(s) c’est le chercheur qui doit s’il le peut lui donner un sens …

    J’ose : ” Science sans conscience , n’est que ruine de l’âme ( Vous savez qui) ”

    Par contre : je recommande l’usage de ce genre d’outils une fois le modèle bien établi pour examiner : soit à quels pièges vous avez échappé soit que vous êtes passé à côté de la question et qu’il tout recommencer …

    Très cordialement.
    Paradoxalix

  7. Bonjour Della très gentile de votre par cet article me fera beaucoup de bien dans mais prochaines analyses.
    j’aimerais vous demander si cela est possible bien d’avoir un article qui traite de l’apurement des données?
    Très cordialement à vous

  8. Une très belle découverte. Au contraire de ce que certains peuvent en dire, je ne pense pas que cet outil soit un prétexte à l’absence de calcul réalisé par nos soins ou l’absence de réflexion préalable à notre jeu de données, mais c’est surtout un moyen d’aider des personnes pour lesquelles les commandes dans R restent encore un peu obscures. Nous pouvons très bien comprendre ce que chaque graphique automatiquement généré illustre et vérifier par nous-même ensuite de potentielles erreurs par rapport à nos résultats, mais c’est une réelle aide pour sonder un jeu de données rapidement et sans frustration de se tromper dans les codes de R.
    Merci pour vos articles, de précieuses pépites dans le cadre de mes analyses en écologie. 🙂

  9. Bonjour Della,
    Votre article est très riche. Grand merci à vous.
    Est-ce possible de réaliser un article qui porte sur l’apurement des données?
    Merci bien

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bonjour !

vous venez souvent ?

Identifiez-vous pour avoir accès à toutes les fontionnalités !

Aide mémoire off'R ;)

Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.