library(tidyverse)
On considère le jeu de données diamonds
qui contient le prix ainsi que certaines caractéristiques de 54000 diamants (pour des informations sur des prix des diamants , voir le site http://www.diamonds.info/)
Ici, on dispose de 10 variables
- cut : qualité de la coupe du diamant
- price : prix du diamant
- clarity : clarté du diamant
- carat : poid
- depth
- ....
Taper la comande help(diamonds)
.
data("diamonds")
dim(diamonds)
## [1] 53940 10
head(diamonds)
## # A tibble: 6 x 10
## carat cut color clarity depth table price x y z
## <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
## 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
## 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
## 4 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63
## 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
## 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
summary(diamonds)
## carat cut color clarity
## Min. :0.2000 Fair : 1610 D: 6775 SI1 :13065
## 1st Qu.:0.4000 Good : 4906 E: 9797 VS2 :12258
## Median :0.7000 Very Good:12082 F: 9542 SI2 : 9194
## Mean :0.7979 Premium :13791 G:11292 VS1 : 8171
## 3rd Qu.:1.0400 Ideal :21551 H: 8304 VVS2 : 5066
## Max. :5.0100 I: 5422 VVS1 : 3655
## J: 2808 (Other): 2531
## depth table price x
## Min. :43.00 Min. :43.00 Min. : 326 Min. : 0.000
## 1st Qu.:61.00 1st Qu.:56.00 1st Qu.: 950 1st Qu.: 4.710
## Median :61.80 Median :57.00 Median : 2401 Median : 5.700
## Mean :61.75 Mean :57.46 Mean : 3933 Mean : 5.731
## 3rd Qu.:62.50 3rd Qu.:59.00 3rd Qu.: 5324 3rd Qu.: 6.540
## Max. :79.00 Max. :95.00 Max. :18823 Max. :10.740
##
## y z
## Min. : 0.000 Min. : 0.000
## 1st Qu.: 4.720 1st Qu.: 2.910
## Median : 5.710 Median : 3.530
## Mean : 5.735 Mean : 3.539
## 3rd Qu.: 6.540 3rd Qu.: 4.040
## Max. :58.900 Max. :31.800
##
Le package ggplot2 reproduit la grammaire des graphiques (voir Grammar of Graphics, Leland Wilkinson), avec le même formalisme. Le principe de cette grammaire est qu’un graphique est composé de couches (voir la site http://ggplot2.org/ pour plus d’information).
Qu’est ce qu’un graphique ?
Prenons l’exemple d’un diagramme en barres pour la variable cut qui représente la qualité de la coupe du diamant.
Une première tentative consiste à définir les axes. On va utiliser la fonction ggplot()
. Le jeu de données est un data-frame que l’on renseignera dans le fonction ggplot et les variables seront spécifiées dans la fonction aes
.
ggplot(data = diamonds, aes(x = cut))
Nous allons representer graphiquement chaque modalité de la variable cut
. Pour ce faire nous ajoutons la fonction géométrique geom_bar()
.
ggplot(diamonds, aes(x = cut)) + geom_bar()
En résumé, ici le jeu de données est renseigné dans la fonction ggplot, la variable à représenter dans la fonction aes, le type de représentation souhaitée est spécifié ensuite par la fonction geom_bar()
. Les 2 instructions sont séparées par un +
. C’est le schéma classique de construction de graphes avec ggplot2.
La fonction aes admet également des arguments tels que color, size, fill. Ces arguments sont à utiliser par exemple lorsqu’une couleur est définie à partir d’une variable du jeu de données. Si pour la représentation précédente on souhaite une couleur différente selon les modalités de la variable cut, on ajoutera color = cut
dans aes
:
ggplot(diamonds, aes(x = cut, color = cut)) + geom_bar()
ggplot(diamonds, aes(x = cut, fill = cut)) + geom_bar()
ggplot(diamonds, aes(x = cut, fill = cut)) +
geom_bar() +
ggtitle("Representation de la variable cut") +
xlab(" ") +
ylab("Effectif")
Par defaut les couleurs sont rangées de la plus sombre à la plus claire. On peut changer la palette de couleur par exemple à l’aide de la fonction scale_fill_brewer()
. Voir par exemple help(scale_fill_brewer)
.
ggplot(diamonds, aes(x = cut, fill = cut)) + geom_bar() +
scale_fill_brewer(type="qual", palette = 6)
On peut également changer les couleurs manuellement avec la fonction scale_fill_manual()
.
ggplot(diamonds, aes(x = cut, fill = cut)) + geom_bar() +
scale_fill_manual(values = c(Fair= "red", Good = "blue", "Very Good" = "green", "Premium" = "pink", "Ideal" = "orange"))
On peut préférer vouloir avoir des proportions (valeurs entre 0 et 1). On utilise la variable ..count.. (stocké avec R automatiquement quand on fait ce graphique) qui représente le nombre de lignes pour chaque modalité. Ensuite on calcule la proportion à la main à l’aide des commandes ci-dessous.
ggplot(diamonds, aes(x = cut, fill = cut)) +
geom_bar(aes(y = ..count../sum(..count..))) +
ylab("proportion")
Sinon on peut aussi creer notre prope formule et l’ajouter dans notre tableau des données et ensuite faire un graphique (voir les commandes ci-dessous).
tmp <- diamonds %>% count(cut) %>%
mutate(prop = n/sum(n))
ggplot(data=tmp,aes(x=cut,y=prop,fill=cut)) +
geom_bar(stat="identity")
Pour finir cette partie, comment faire un camembert ? A vous de jouer !
Retour sur la grammaire ggplot
Comme nous venons de le voir, une représentation graphique ggplot se construit à partir d’un ensemble d’éléments indépendants. Ces éléments constituent la grammaire de la syntaxe. Les principaux éléments de cette grammaire dans ggplot2 sont :
Une aide précieuse
Lorsque vous écrivez vos graphes, reportez vous à la Cheat Sheet ggplot2. En 2 pages, elle présente l’ensemble des fonctionnalités de bases que vous pouvez combiner ! https://www.rstudio.com/wp-content/uploads/2015/03/ggplot2-cheatsheet.pdf
mean(diamonds$price)
## [1] 3932.8
median(diamonds$price)
## [1] 2401
summary(diamonds$price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 326 950 2401 3933 5324 18823
Imaginons qu’on veut savoir :
- Combiens de diamants coutent moins de U$500?
- Combiens de diamants coutent moins de U$250?
_ Combiens de diamants coutent plus que $15000 ?
sum(diamonds$price < 500)
## [1] 1729
diamonds %>% filter(price <500 ) %>% count()
## # A tibble: 1 x 1
## n
## <int>
## 1 1729
diamonds %>% filter(price <250 ) %>% count()
## # A tibble: 1 x 1
## n
## <int>
## 1 0
diamonds %>% filter(price > 15000 ) %>% count()
## # A tibble: 1 x 1
## n
## <int>
## 1 1655
L’histogramme de la variable continue price s’obtient comme suit
ggplot(data=diamonds, aes(x=price)) + geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(data=diamonds, aes(x=price)) + geom_histogram(binwidth=500)
ggplot(data=diamonds, aes(x=price)) + geom_histogram(binwidth=500,boundary = 0)
Il y a un pic très visible dans l’histogramme. Approchons-nous de très près pour observer la fréquence plus élevée que prévu.
ggplot(diamonds,aes(x=price)) +
geom_histogram(binwidth=500,boundary = 0) +
xlim(0,2500)
## Warning: Removed 26398 rows containing non-finite values (stat_bin).
Un peu bloqué ? La largeur de la fenêtre (binwidth) n’est définitivement pas la meilleure, car nous l’avons laissée à 500 et avons mis une limite de valeur à moins de 2500 dollars. On devrait peut-être baisser la largeur de la fenêtre pour voir comment ça change l’image :
ggplot(data=diamonds,aes(x=price)) + geom_histogram(binwidth=100, boundary = 0) + xlim(0,2500)
## Warning: Removed 26398 rows containing non-finite values (stat_bin).
Que peu-t-on remarquer ? En changeant la taille de la fenêtre à 100 la fréquence maximale est passée de 10000 diamants à 2000 diamants. Il s’agit d’un changement réel dans le graphique, mais impossible à voir si vous ne changez pas la taille de la fenêtre manuellement.
On va se ramener à une fonction que ne change pas en fonction de la taille de la boite. Plutot que regarder l’effectif on va calculer la densité. Regardons la commande suivante
ggplot(data=diamonds, aes(x=price)) + geom_histogram(aes(y = ..density..), binwidth=100) + xlim(0,2500)
## Warning: Removed 26398 rows containing non-finite values (stat_bin).
## Warning: Removed 2 rows containing missing values (geom_bar).
On va utiliser maintenant la fonction geom_density
. Ce fonction calcule et dessine l’estimation de la densité par noyau, qui est une version lissée de l’histogramme.
ggplot(data=diamonds, aes(x=price)) + geom_density()
On peut jouer avec un paramètre proportionel à la fenetre choisi automatiquement avec l’argument adjust
…
ggplot(data=diamonds, aes(x=price)) + geom_density(adjust = 0.1)
Conclusion par rapport à la fenêtre :
On a remarqué que si elle est trop grande c’est trop simplifié et si elle est trop petite c’est trop agité … Un grand problème en statistique est le choix de la taille de la fenêtre!
Imaginons que nous voulons afficher les différentes valeurs de price en fonction de la variable cut
ggplot(data=diamonds,aes(x=cut,y=price,color=cut)) + geom_point()
Que peut-on remarquer avec la commande suivante ?
ggplot(data=diamonds,aes(x=cut,y=price,color=cut)) +
geom_point(position = "jitter")
Ici jitter
ajoute une petite quantité de variation aléatoire à l’emplacement de chaque point et constitue un moyen utile de mieux visualiser les points.
ggplot(data=diamonds,aes(x=cut,y=price,color=cut)) +
geom_point(position = "jitter", alpha = 0.05)
Le geom_jitter
est un raccourci pratique pour geom_point(position = "jitter")
ggplot(data = diamonds,
aes(x = cut, y = price, color = cut)) +
geom_jitter(alpha = 0.05)
Imaginons que nous voulons afficher les différentes valeurs de price en fonction de la variable cut à l’aide d’une boîte à moustache
ggplot(data = diamonds, aes(x = cut, y = price, color = cut)) +
geom_boxplot()
ggplot(data = diamonds, aes(x = cut, y = price, color = cut)) +
geom_boxplot(aes(fill = cut))
ggplot(data = diamonds,
aes(x = cut, y = price, color = cut)) +
geom_point(position = "jitter", alpha = 0.03) +
geom_boxplot()
ggplot(diamonds, aes(x=cut, y= price, fill=cut)) + geom_boxplot()
ggplot(diamonds, aes(x=cut, y= price, fill=cut)) + geom_boxplot() + coord_cartesian(ylim=c(0,8000))
j’ai fait un zoom pour éviter de voir un trop grand nombre de valeurs aberrantes en utilisant ylim=c(0,8000). Il semble que la coupe de tous les types comporte des prix de tous les types…Ce qui est surprenant en regardant ce graphique est que les diamants idéaux sont moins chers que les diamants moyens.
Voyons le même diagramme en utilisant la clarté
ggplot(diamonds, aes(factor(clarity), price, fill=clarity)) +
geom_boxplot() +
coord_cartesian(ylim = c(0,8000))
Nous obtenons même quelques valeurs aberrantes. La clarté est donc une variable significative là où la coupe ne l’est pas. Nous pouvons conclure que les gens apprécient plus les mauvais diamants (les moins brillants). C’est bizarre car on a tendance à imaginer que les gens prefierent les diamands plus brillant
Pourquoi ce phénomène ? Est-ce qu’on a pas oublié de voir une variable ???
Regardons la variable (carat) poids ???? Est-ce que le prix d’un diamant depend de son poids ? Conclusion pour la fin : les diamands idéaux sont souvent de taille petite, c’est qui est raisonable car c’est plus difficile à tailler !
Si on souhaite par exemple représenter la variable price en fonction de carat (poids), on utilisera
ggplot(diamonds, aes(x = carat, y = price)) + geom_point()
La relation entre le prix et le poids (carrat) est non-linéaire. Plus le diamant est gros, plus le prix est important. Notez qu’en raison de la très grande taille de l’échantillon, utiliser la transparence permet de mieux visualiser les données.
ggplot(diamonds, aes(x = carat, y = price)) + geom_point(position ="jitter", alpha = 0.05)
Nuage de points avec couleurs venant d’une variable quantitative
ggplot(diamonds, aes(x=carat, y=price)) +
geom_point(aes(color= carat))
Regardons le nuage de points avec couleurs venant de la variable cut
. On observe l’influence de la coupe et de la qualité sur le prix.
ggplot(diamonds, aes(x=carat, y=price)) +
geom_point(aes(color= cut))
Pour comparer des données, il est très intéressant de faire des graphiques de type small multiples. L’idée est de faire un même graphique, mais pour chaque modalité d’une variable. Pour faire nous utilisons la fonction facet_wrap()
. Cette fonction permet de s’affranchir de la réflexion du nombre de modalités dans la variable en question.
Ci-dessous, nous représentons le nuage de points entre carat et price, mais pour chaque valeur de cut.
ggplot(diamonds, aes(x = carat, y = price)) +
geom_point() +
facet_wrap(facets = ~ cut)
ggplot(diamonds, aes(x = carat, y = price)) +
geom_point() +
facet_wrap(~ cut)
ggplot(diamonds, aes(x = carat, y = price,color = clarity)) +
geom_point(alpha = 0.1)
ggplot(diamonds, aes(x = carat, y = price)) +
geom_point(aes(color = clarity),alpha = 0.1)
ggplot(diamonds, aes(x = carat, y = price)) +
geom_point(aes(color = clarity), alpha = .1) +
geom_smooth()
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
ggplot(diamonds, aes(x = carat, y = price)) +
geom_point(aes(color = clarity), alpha = .1) +
geom_smooth(aes(color = clarity))
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
les transformations statistiques (ajustement, …)
Une petite regression (geom_smooth…)
Lorsque l’on dispose de données multivariées, il est utile d’afficher dans une même fenêtre graphique plusieurs graphes correpondants aux différents sous-ensembles.
ggplot(diamonds, aes(x = carat, y = price)) +
geom_point() +
facet_grid(~ cut) + geom_smooth()
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
ggplot(diamonds, aes(x = carat, y = price, color = cut)) +
geom_point() +
geom_smooth()
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
A vous de jouer ! Obtenir le nuage de points carat/price avec une couleur différente selon cut
Le tableau ci-dessous donne quelques exemples de fonctions (accompagnés des aesthetics) permettant de faire les représentations graphiques classiques.
Geom | Description | Aesthetics |
---|---|---|
geom_point() | Nuage de points | x, y, shape, fill |
geom_line() | Ligne (ordonnée selon x) | x, y, linetype |
geom_abline() | Droite | slope, intercept |
geom_path() | Ligne (ordre original) | x, y, linetype |
geom_text() | Texte | x, y, label, hjust, vjust |
geom_rect() | Rectangle | xmin, xmax, ymin, ymax, fill, linetype |
geom_polygon() | Polygone | x, y, fill, linetype |
geom_segment() | Segment | x, y, fill, linetype |
geom_bar() | Diagramme en barres | x, fill, linetype, weight |
geom_histogram() | Histogramme | x, fill, linetype, weight |
geom_boxplot() | Boxplots | x, y, fill, weight |
geom_density() | Densité | x, y, fill, linetype |
geom_contour() | Lignes de contour | x, y, fill, linetype |
geom_smooth() | Lissage | x, y, fill, linetype |
Tous | color, size, group |
Chaque geom
admet également des arguments particuliers permettant de modifier le graphe (couleur, taille de points, épaisseur de traits, etc.).
esquisse::esquisser()