library(tidyverse)

Les données diamonds

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  
## 

Package ggplot2

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 ?

Répresentation d’une variable qualitative

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 :

  • Data : le jeu de données qui contient les variables que l’on veut représenter ;
  • Aesthetic (aes) : spécification des variables à représenter, on inclut également les couleurs, les tailles des objets à représenter ;
  • Geometries (geom_…) : spécification du type de représentation graphique souhaitée ;

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

Une variable quantitative

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!

2 variables : qualitative et quantitative

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 !

2 variables quantitatives

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))

Faceting

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()