Introduction à R - partie 5 (analyse exploratoire)
Auteur·rice
Aurélie Labbe
Analyse exploratoire
Nous allons ici vous donner un exemple de code R qui permet de faire l’analyse exploratoire d’un jeu de données. Je vous rappelle que l’étape d’exploration est cruciale qu’elle que soit l’analyse que vous effectuez et est trop souvent négligée.
Les données que nous allons analyser proviennent du site Kaggle et contiennent les prix de vente de 21 613 maisons vendues dans l’État de Washington entre mai 2014 et mai 2015 dans le comté de King, qui inclut la ville de Seattle. Ce jeu de données contient aussi 19 variables mesurant différentes caractéristiques des habitations. Ces variables sont détaillées ci-dessous:
id: numéro d’identifiant de la propriété
date: date de vente de la propriété
price: prix de vente de la propriété (variable d’intérêt)
bedrooms: nombre de chambres
bathrooms: nombre de salles de bain
sqft_living: superficie en pieds carrés (intérieur)
sqft_lot: superficie en pieds carrés (lot au complet)
floors: nombre d’étages
waterfront: vue sur la mer (1=oui, 0=non)
view: nombre de vues de la propriété dans l’agence immobilière (note: aucune explication n’est donnée sur la signification de cette variable)
condition: condition de la propriété (score de 1 à 5) en fonction de son âge et de son état (1=mauvaise, 2=acceptable, 3=moyen, 4=bon, 5=très bon). Ce score est calculé selon le système de notation du comté de King.
grade: score global selon la qualité des rénovations et des matériaux de construction (score de 1 à 13 - un score élevé correspond à des matériaux utilisés de meilleure qualité). Ce score est calculé selon le système de notation du comté de King.
sqft_above: superficie de la propriété excluant le sous-sol
sqft_basement: superficie du sous-sol
yr_built: année de construction
yr_renovated: année des dernières rénovations
zip: code postal
lat: latitude
long: longitude
Voici le code qui permet de lire les données:
# install.packages("MAVE")# Extraire directement les données Kaggle d'un paquetdata(kc_house_data, package ="MAVE")maisons <- kc_house_data # renommer pour faciliter l'analysestr(maisons)
Nous pouvons commencer par faire des résumés numériques de toutes les variables pour identifier les valeurs manquantes, les valeurs aberrantes (en regardant le min et max) et évaluer rapidement leur distribution en regardant les quartiles. Ceci peut se faire à l’aide de la fonction summary, comme dans l’exemple ci-dessous:
summary(maisons$price)
Exercice 1 À l’aide de la function summary, évaluez le profile des variables quantitatives. Quels sont les éléments qui retiennent particulièrement votre attention? Y-a-t-il des données aberrantes ou extrêmes à considérer plus attentivement?
Des histogrammes et des boîtes à moustaches des variables quantitatives permettent de visualiser la distribution des données. Ces graphiques sont un bon moyen d’évaluer la normalité et symmétrie des variables.
# Variable "price"par(mfrow =c(1, 2))prix <- maisons$price # prixhist(prix /1e5, # modifier échelle pour clarté des étiquettesmain ="", ylab ="fréquence",xlab ="prix (en 100K USD)")# Boîte à moustache - pas adéquat vu le volumeboxplot(prix /1e5,horizontal =FALSE,main ="", # libellé du titrexlab ="prix (en 100K USD)",log ="y") #libellé de l'axe des x
Nous voyons par exemple que la distribution de la variable prix est très asymétrique vers la droite. Si nous voulons par la suite utiliser un modèle de régression linéaire pour modèliser le prix des maisons, la transformation log sera très probablement nécessaire pour éviter l’impact des extrêmes.
hist(log(prix, base =10),main ="", ylab ="fréquence",xlab ="prix (en log 10 USD)")
boxplot(log(prix, base =10),horizontal =FALSE,# log = "y" # mettre un axe logarithmique avec données brutesmain ="", # libellé du titrexlab ="prix (en log(10) USD)")
Comprendre et explorer les données implique l’exploration un peu plus approfondie de certaines variables afin d’avoir une idéee précise du profil de nos données. Par exemple, vous devriez pouvoir répondre à des questions de base comme par exemple de connaître le nombre de maisons par catégorie de prix. Voici un exemple de code qui pourrait répondre à ces questions
# Pourcentage des observations qui excèdent 200K, 300K, 400Ksapply(c(2e5, 3e5, 4e5), function(val){mean(prix > val)})
[1] 0.9610882 0.7885532 0.5910332
La distribution des variables numériques catégorielles, telles que le nombre de chambres, salle de bain, etc. peut être calculée à l’aide de la fonction table:
Exercice 2 À l’aide de la function table, évaluez le profile des variables numériques catégorielles. Quels sont les éléments qui retiennent particulièrement votre attention?
Exercice 3 Combien y a-t-il de code postaux différents dans la base de données?
Exercice 4 Faites toujours quelques petites vérifications de base sur vos données (soyez curieux et créatifs!) Par exemple, est-ce que la somme des superficies à l’étage et au sous-sol est bien égale à la superficie totale ? Vous pouvez vérifier aussi par exemple que lorsque sqft_living > sqft_lot, c’est que la propriété a plusieurs étages.
Exploration des données: croiser les variables
Lorsque l’on utilise un modèle linéaire pour prédire une variable d’intérêt \(Y\), il est important de vérifier que la relation entre \(Y\) et chacun des prédicteurs \(X\) est belle et bien linéaire. Si un modèle linéaire est ajusté sur des données montrant une relation quadratique ou log-linéaire par exemple, la qualité de prédiction peut être grandement affectée. Il est donc important de regarder au préalable quel type de relation (linéaire ou nonlinéaire) semble exister entre chacun des prédicteurs et la variable d’intérêt. Voici maintenant une série de commandes qui vont vous permettre d’évaluer la relation entre le prix des maisons et leurs caractéristiques. N’hésitez pas à enlever les valeurs extrêmes de vos graphiques (pas du jeu de données !) pour avoir une meilleure idée des relations. Vous pouvez aussi regarder la relation avec le logarithme des variables, pour évaluer quelle transformation donne la meilleure relation linéaire entre les variables.
# Bedroomspar(mfrow =c(2, 2), pch =20, bty ="l")plot(I(price /1e5) ~ bedrooms, data = maisons,xlab ="nombre de chambres", ylab ="prix (en 100K USD)")plot(log(price, base =10) ~ bedrooms, data = maisons,xlab ="nombre de chambres", ylab ="prix (en log[10] USD)")with(maisons |> dplyr::filter(bedrooms <9),plot(x = bedrooms,y = price /1e5, xlab ="nombre de chambres", ylab ="prix (en 100K USD)"))with(maisons |> dplyr::filter(bedrooms <9),plot(x = bedrooms,y =log(price, base =10), # base 10 pour interprétabilité xlab ="nombre de chambres", ylab =expression("prix (en log[10] USD)")))
Exercice 5 Répétez cette opération pour les autres variables. Quelles tendances se dégagent?
Exploration des données: ggplot
La librairie ggplot2 permet de réaliser des graphiques plus complexes et de qualité bien supérieure à ceux de la fonction de base plot. Vous pouvez consulter la galerie de graphiques produits avec ggplot en ligne.
Nous n’allons pas faire une introduction complète à ggplot2 ici (ce serait bien trop long, il y a des livres entiers sur le sujet), mais vous donner quelques exemples de graphiques de visualisation de données. La syntaxe de ggplot2 est par contre différente des autres fonctions R classiques, et cela demande un peu d’adaptation. Un graphique consiste en effet en une succession de commandes séparée avec le symbole +.
Avant de commencer, assurez-vous que vous avez installé les paquets ggplot2, patchwork et ggridges.
Commençons par effectuer un histogramme et un diagramme à bandes pour la variable price. La fonction ggplot permet de définir le cadre du graphique de base et de définir quelles sont les variables qui vont être inclues.
library(ggplot2) # grammaire des graphiqueslibrary(patchwork) # combiner des objets ggplottheme_set(theme_classic()) # choisir le thème graphique
En combinant la fonction de base ggplot avec d’autres fonctions spécifiques, toutes sortes de graphiques peuvent être réalisés, comme un histogramme par exemple:
ggplot(data = maisons, mapping =aes(x = price /1e5)) +geom_histogram() +# choix de la représentation graphiquescale_y_continuous(limits =c(0, NA),expand =expansion(mult =c(0, 0.1))) +labs(x ="prix (en 100K USD)", # étiquettes des axes, titre, sous-titre, etc.y ="décompte")
Il est possible de controller le nombre de séparations de l’histogramme avec l’option binwidth (largeur des boîtes) ou bins (nombre de catégories), par exemple ici en incréments de 50K dollars.
g1 <-ggplot(maisons, aes(x =log(price, base =10))) +geom_histogram(binwidth =0.5) +labs(x ="prix (log base 10 USD)",y ="décompte",caption ="largeur de boîte de 1/2")
Voici maintenant comment faire un diagramme en boîte de la variable prix à l’échelle logarithmique. Il y a plusieurs options de thèmes et la possibilité, en voici deux exemples:
g1 <-ggplot(maisons, aes(y =log(price, base =10))) +geom_boxplot() +labs(x ="prix (en log[10] USD)")g2 <-ggplot(maisons,aes(y =log(price, base =10))) +geom_boxplot(fill ="gray",color ="black") +theme_minimal()# Combiner des graphiques avec "patchwork"# g1 + g2 pour côte à côte, g1 / g2 pour haut/basg1 + g2
On peut aussi produire des boîtes à moustaches de la variable logprix en fonction du nombre d’étages de la maison, par exemple. Notez qu’il faut pour cela que la variable floors soit convertie en facteur. Différentes options vous sont montrées ci-dessous.
Nous pouvons aussi regarder comment le prix des maisons (échelle log) varie en fonction du nombre de chambres par exemple:
ggplot(maisons, aes(x = bedrooms, y =log(prix, base =10))) +geom_point(alpha = .3) +geom_smooth(method ="lm",se =FALSE,color ="red",linetype ="dashed") +labs(title ="Prix (log base 10 USD) en fonction du nombre de chambres",x ="nombre de chambres",y ="")
Voici un dernier exemple de graphique un peu plus sophistiqué, qui nécessite l’installation du paquet ggridge. Ce graphique permet de voir la distribution du prix des maisons selon la condition.
maisons |> dplyr::mutate(fcondition =factor( condition,labels =c("mauvaise", "acceptable", "moyen", "bon", "très bon")) ) |>ggplot(aes(x = price, y = fcondition)) + ggridges::geom_density_ridges() +scale_x_continuous(transform ="log10",labels = scales::dollar_format(scale = .001,accuracy =1,suffix ="K")) +labs(title ="Prix selon la condition", x ="prix (en USD)", y ="condition") +theme_classic()
Références
Les possibilités avec le paquet ggplot et la grammaire des graphiques sont extrêmement nombreuses. Si vous souhaitez explorer un peu plus le sujet, je vous réfère au livre disponible en ligne ggplot2: Elegant Graphics for Data Analysis