Manipulation des données avec dplyr

dplyr est un package dédié à la simplification de la manipulation, l’exploration et les calculs sur des données.

Nous allons explorer les commandes de base du package dplyr. Pour se faire nous allons utiliser la base flights disponible dans le package ‘nycflights13’

Chargement des packages

library(nycflights13)
library(ggplot2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(formattable)

Les commandes de base

Nous vous présenterons ici 5 des principaux verbes du package {dplyr}. Il en existe d’autres, mais les verbes ci-dessous sont particulièrement indispensables.

Ils ont tous en commun de prendre comme premier argument le nom du jeu de donn?es sur lequel opérer les manipulations.

Ces verbes sont: * select : permet de sélectionner des colonnes de la base ; * filter : permet de sélectionner des lignes de la base répondant à certains critères ; * arrange : permet de réarranger les lignes de la base selon certains critères ; * mutate : permet de créer des variables synthétiques ; * summarise : permet d’aggréger des données.

dim(flights)
## [1] 336776     19
head(flights)
## # A tibble: 6 x 19
##    year month   day dep_time sched_dep_time dep_delay arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>
## 1  2013     1     1      517            515         2      830
## 2  2013     1     1      533            529         4      850
## 3  2013     1     1      542            540         2      923
## 4  2013     1     1      544            545        -1     1004
## 5  2013     1     1      554            600        -6      812
## 6  2013     1     1      554            558        -4      740
## # ... with 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
## #   carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## #   air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>,
## #   time_hour <dttm>

Comment sélectionner des colonnes ?

select(flights, year, month, day)
## # A tibble: 336,776 x 3
##     year month   day
##    <int> <int> <int>
##  1  2013     1     1
##  2  2013     1     1
##  3  2013     1     1
##  4  2013     1     1
##  5  2013     1     1
##  6  2013     1     1
##  7  2013     1     1
##  8  2013     1     1
##  9  2013     1     1
## 10  2013     1     1
## # ... with 336,766 more rows

Cette ligne de code est équivalente à flights[,c("year","month","day")].

Il est possible de sélectionner plusieurs colonnes contigu?s avec “:”

select(flights, year:day)
## # A tibble: 336,776 x 3
##     year month   day
##    <int> <int> <int>
##  1  2013     1     1
##  2  2013     1     1
##  3  2013     1     1
##  4  2013     1     1
##  5  2013     1     1
##  6  2013     1     1
##  7  2013     1     1
##  8  2013     1     1
##  9  2013     1     1
## 10  2013     1     1
## # ... with 336,766 more rows

Il est aussi possible d’anti-sélectionner par les noms de variables :

select(flights, -(year:day))
## # A tibble: 336,776 x 16
##    dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay
##       <int>          <int>     <dbl>    <int>          <int>     <dbl>
##  1      517            515         2      830            819        11
##  2      533            529         4      850            830        20
##  3      542            540         2      923            850        33
##  4      544            545        -1     1004           1022       -18
##  5      554            600        -6      812            837       -25
##  6      554            558        -4      740            728        12
##  7      555            600        -5      913            854        19
##  8      557            600        -3      709            723       -14
##  9      557            600        -3      838            846        -8
## 10      558            600        -2      753            745         8
## # ... with 336,766 more rows, and 10 more variables: carrier <chr>,
## #   flight <int>, tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>,
## #   distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

Par ailleurs d’autres fonctions utiles de sélection sont pré-implémentées : starts_with, ends_with, matches et contains.

Comment filtrer les données

Le deuxième verbe central de dplyr est filter. Il permet de filtrer les lignes du jeu de données qui satisfont un critère. Son écriture est très proche de la fonction subset :

filter(flights, month == 1, day == 1) #ceci est équivalent à flights[flights$month == 1 & flights$day == 1, ]
## # A tibble: 842 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>
##  1  2013     1     1      517            515         2      830
##  2  2013     1     1      533            529         4      850
##  3  2013     1     1      542            540         2      923
##  4  2013     1     1      544            545        -1     1004
##  5  2013     1     1      554            600        -6      812
##  6  2013     1     1      554            558        -4      740
##  7  2013     1     1      555            600        -5      913
##  8  2013     1     1      557            600        -3      709
##  9  2013     1     1      557            600        -3      838
## 10  2013     1     1      558            600        -2      753
## # ... with 832 more rows, and 12 more variables: sched_arr_time <int>,
## #   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>
filter(flights, month == 1 | month == 2)
## # A tibble: 51,955 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>
##  1  2013     1     1      517            515         2      830
##  2  2013     1     1      533            529         4      850
##  3  2013     1     1      542            540         2      923
##  4  2013     1     1      544            545        -1     1004
##  5  2013     1     1      554            600        -6      812
##  6  2013     1     1      554            558        -4      740
##  7  2013     1     1      555            600        -5      913
##  8  2013     1     1      557            600        -3      709
##  9  2013     1     1      557            600        -3      838
## 10  2013     1     1      558            600        -2      753
## # ... with 51,945 more rows, and 12 more variables: sched_arr_time <int>,
## #   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>

Comment trier les données ?

Une autre opération utile consiste à trier le jeu de données, dans l’ordre croissant ou décroissant selon un ou plusieurs critères : c’est le job de la fonction arrange.

Par défaut, le tri se fait en ordre croissant :

arrange(flights, year)
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>
##  1  2013     1     1      517            515         2      830
##  2  2013     1     1      533            529         4      850
##  3  2013     1     1      542            540         2      923
##  4  2013     1     1      544            545        -1     1004
##  5  2013     1     1      554            600        -6      812
##  6  2013     1     1      554            558        -4      740
##  7  2013     1     1      555            600        -5      913
##  8  2013     1     1      557            600        -3      709
##  9  2013     1     1      557            600        -3      838
## 10  2013     1     1      558            600        -2      753
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## #   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>

C’est en utilisant la fonction desc() que le tri se fait en ordre décroissant. Un genre de decreasing = TRUE de la fonction sort :

arrange(flights, desc(arr_delay))
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>
##  1  2013     1     9      641            900      1301     1242
##  2  2013     6    15     1432           1935      1137     1607
##  3  2013     1    10     1121           1635      1126     1239
##  4  2013     9    20     1139           1845      1014     1457
##  5  2013     7    22      845           1600      1005     1044
##  6  2013     4    10     1100           1900       960     1342
##  7  2013     3    17     2321            810       911      135
##  8  2013     7    22     2257            759       898      121
##  9  2013    12     5      756           1700       896     1058
## 10  2013     5     3     1133           2055       878     1250
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## #   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>

On peut cumuler plusieurs critères. Les données sont alors rangées selon l’ordre lexicographique défini par les variables d’entrée.

arrange(flights, year, month, day)
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>
##  1  2013     1     1      517            515         2      830
##  2  2013     1     1      533            529         4      850
##  3  2013     1     1      542            540         2      923
##  4  2013     1     1      544            545        -1     1004
##  5  2013     1     1      554            600        -6      812
##  6  2013     1     1      554            558        -4      740
##  7  2013     1     1      555            600        -5      913
##  8  2013     1     1      557            600        -3      709
##  9  2013     1     1      557            600        -3      838
## 10  2013     1     1      558            600        -2      753
## # ... with 336,766 more rows, and 12 more variables: sched_arr_time <int>,
## #   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>

Comment transformer des variables, en créer des nouvelles ?

mutate est le verbe qui permet la transformation d’une variable existante ou la création d’une nouvelle variable dans le jeu de données. C’est le verbe à utiliser dès lors qu’on utilise $ et <- dans la même instruction, comme dans : dataset$nouvelle_variable <- op?éation sur une ancienne_variable ou dataset$ancienne_variable <- opération sur une ancienne_variable

mutate(flights,
  gain = arr_delay - dep_delay,
  speed = distance / air_time * 60)
## # A tibble: 336,776 x 21
##     year month   day dep_time sched_dep_time dep_delay arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>
##  1  2013     1     1      517            515         2      830
##  2  2013     1     1      533            529         4      850
##  3  2013     1     1      542            540         2      923
##  4  2013     1     1      544            545        -1     1004
##  5  2013     1     1      554            600        -6      812
##  6  2013     1     1      554            558        -4      740
##  7  2013     1     1      555            600        -5      913
##  8  2013     1     1      557            600        -3      709
##  9  2013     1     1      557            600        -3      838
## 10  2013     1     1      558            600        -2      753
## # ... with 336,766 more rows, and 14 more variables: sched_arr_time <int>,
## #   arr_delay <dbl>, carrier <chr>, flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>, gain <dbl>, speed <dbl>

Comment résumer les données ?

summarize est une fonction dite de “résumé”. A l’inverse de mutate, quand une fonction summarize est appelée, elle retourne une seule information. La moyenne, la variance, l’effectif, etc, sont des informations qui condensent la variable étudiée en une seule information.

summarise(flights,
  delay = mean(dep_delay, na.rm = TRUE))
## # A tibble: 1 x 1
##      delay
##      <dbl>
## 1 12.63907

Enchaîner les opérations de manipulations de données

Le package {magrittr} propose un opérateur codé %>% dont le rôle est d’éviter l’imbrication des fonctions les unes dans les autres. Par exemple :

flights %>% head()
## # A tibble: 6 x 19
##    year month   day dep_time sched_dep_time dep_delay arr_time
##   <int> <int> <int>    <int>          <int>     <dbl>    <int>
## 1  2013     1     1      517            515         2      830
## 2  2013     1     1      533            529         4      850
## 3  2013     1     1      542            540         2      923
## 4  2013     1     1      544            545        -1     1004
## 5  2013     1     1      554            600        -6      812
## 6  2013     1     1      554            558        -4      740
## # ... with 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
## #   carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## #   air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>,
## #   time_hour <dttm>
# est ?quivalent ?: head(flights)

Dans l’exemple précédent, la fonction head prend le jeu de données ‘flights’ comme premier argument.

L’intérêt de cet opérateur %>% n’est pas pleinement exprimé dans cet exemple, puisque qu’on ne gagne pas particulièrement en lisibilité ou en frappe sur le clavier. Son intérêt réside en fait dans le chaînage des opérations de manipulation sur la base de données.

flights %>%
  filter(month > 6) %>%
  summarise(delay2 = mean(dep_delay, na.rm = TRUE)) %>%
  mutate(delay_minute = delay2*60)
## # A tibble: 1 x 2
##     delay2 delay_minute
##      <dbl>        <dbl>
## 1 11.60091     696.0547

Réaliser les traitements par groupe dans un “pipe”

Découper un jeu de données pour réaliser des opérations sur chacun des sous-ensembles afin de les restituer ensuite de façon organisée est appelée stratégie du split - apply. Cette opération est réalisée par la fonction group_by. Dans un pipe, dès lors qu’un group_by est introduit, toutes les opérations qui suivent sont réalisées pour chacun des sous-ensembles de la base.

flights %>%
  group_by(year, month, day)%>%
  select(arr_delay, dep_delay) %>%
  summarise(
    arr = mean(arr_delay, na.rm = TRUE),
    dep = mean(dep_delay, na.rm = TRUE)
  ) %>%
  filter(arr > 30 | dep > 30) %>%
  arrange(month, day)
## Adding missing grouping variables: `year`, `month`, `day`
## # A tibble: 49 x 5
## # Groups:   year, month [11]
##     year month   day      arr      dep
##    <int> <int> <int>    <dbl>    <dbl>
##  1  2013     1    16 34.24736 24.61287
##  2  2013     1    31 32.60285 28.65836
##  3  2013     2    11 36.29009 39.07360
##  4  2013     2    27 31.25249 37.76327
##  5  2013     3     8 85.86216 83.53692
##  6  2013     3    18 41.29189 30.11796
##  7  2013     4    10 38.41231 33.02368
##  8  2013     4    12 36.04814 34.83843
##  9  2013     4    18 36.02848 34.91536
## 10  2013     4    19 47.91170 46.12783
## # ... with 39 more rows

Une application

On va appliquer les principes précédents pour manipuler une base de données regroupant un certain nombre d’informations sur des longs métrages disponibles sur une plate-forme de streaming.

movie <-read.csv('movie_metadata.csv',header=T,stringsAsFactors = F)
head(movie)
##   color     director_name num_critic_for_reviews duration
## 1 Color     James Cameron                    723      178
## 2 Color    Gore Verbinski                    302      169
## 3 Color        Sam Mendes                    602      148
## 4 Color Christopher Nolan                    813      164
## 5             Doug Walker                     NA       NA
## 6 Color    Andrew Stanton                    462      132
##   director_facebook_likes actor_3_facebook_likes     actor_2_name
## 1                       0                    855 Joel David Moore
## 2                     563                   1000    Orlando Bloom
## 3                       0                    161     Rory Kinnear
## 4                   22000                  23000   Christian Bale
## 5                     131                     NA       Rob Walker
## 6                     475                    530  Samantha Morton
##   actor_1_facebook_likes     gross                          genres
## 1                   1000 760505847 Action|Adventure|Fantasy|Sci-Fi
## 2                  40000 309404152        Action|Adventure|Fantasy
## 3                  11000 200074175       Action|Adventure|Thriller
## 4                  27000 448130642                 Action|Thriller
## 5                    131        NA                     Documentary
## 6                    640  73058679         Action|Adventure|Sci-Fi
##      actor_1_name                                             movie_title
## 1     CCH Pounder                                                 Avatar 
## 2     Johnny Depp               Pirates of the Caribbean: At World's End 
## 3 Christoph Waltz                                                Spectre 
## 4       Tom Hardy                                  The Dark Knight Rises 
## 5     Doug Walker Star Wars: Episode VII - The Force Awakens             
## 6    Daryl Sabara                                            John Carter 
##   num_voted_users cast_total_facebook_likes         actor_3_name
## 1          886204                      4834            Wes Studi
## 2          471220                     48350       Jack Davenport
## 3          275868                     11700     Stephanie Sigman
## 4         1144337                    106759 Joseph Gordon-Levitt
## 5               8                       143                     
## 6          212204                      1873         Polly Walker
##   facenumber_in_poster
## 1                    0
## 2                    0
## 3                    1
## 4                    0
## 5                    0
## 6                    1
##                                                      plot_keywords
## 1                           avatar|future|marine|native|paraplegic
## 2     goddess|marriage ceremony|marriage proposal|pirate|singapore
## 3                              bomb|espionage|sequel|spy|terrorist
## 4 deception|imprisonment|lawlessness|police officer|terrorist plot
## 5                                                                 
## 6               alien|american civil war|male nipple|mars|princess
##                                        movie_imdb_link
## 1 http://www.imdb.com/title/tt0499549/?ref_=fn_tt_tt_1
## 2 http://www.imdb.com/title/tt0449088/?ref_=fn_tt_tt_1
## 3 http://www.imdb.com/title/tt2379713/?ref_=fn_tt_tt_1
## 4 http://www.imdb.com/title/tt1345836/?ref_=fn_tt_tt_1
## 5 http://www.imdb.com/title/tt5289954/?ref_=fn_tt_tt_1
## 6 http://www.imdb.com/title/tt0401729/?ref_=fn_tt_tt_1
##   num_user_for_reviews language country content_rating    budget
## 1                 3054  English     USA          PG-13 237000000
## 2                 1238  English     USA          PG-13 300000000
## 3                  994  English      UK          PG-13 245000000
## 4                 2701  English     USA          PG-13 250000000
## 5                   NA                                        NA
## 6                  738  English     USA          PG-13 263700000
##   title_year actor_2_facebook_likes imdb_score aspect_ratio
## 1       2009                    936        7.9         1.78
## 2       2007                   5000        7.1         2.35
## 3       2015                    393        6.8         2.35
## 4       2012                  23000        8.5         2.35
## 5         NA                     12        7.1           NA
## 6       2012                    632        6.6         2.35
##   movie_facebook_likes
## 1                33000
## 2                    0
## 3                85000
## 4               164000
## 5                    0
## 6                24000

On peut dans un premier temps dénombrer les films évalués par années

temp <- movie %>% 
  select(movie_title, title_year) %>%
  filter( !is.na(title_year) & !is.na(movie_title) ) %>%
  group_by(title_year) %>%
  summarise(n_film = n())
ggplot(temp,aes(x=title_year,y=n_film))+geom_line()+geom_smooth()
## `geom_smooth()` using method = 'loess'

On peut ensuite résumer l’évolution des notations IMDB au fil des années.

temp1 <- movie %>%
  select(imdb_score, title_year) %>%
  filter(!is.na(title_year) & !is.na(imdb_score)) %>%
  group_by(title_year) %>%
  summarise(score=mean(imdb_score))
ggplot(temp1,aes(x=title_year,y=score))+geom_line()+geom_smooth()
## `geom_smooth()` using method = 'loess'

On peut extraire la liste des 20 réalisateurs les mieux notés :

temp3 <- movie %>% 
  select(director_name, imdb_score) %>%
  filter(!is.na(director_name) & !is.na(imdb_score)) %>%
  group_by(director_name) %>%
  summarise(avg=mean(imdb_score)) %>%
  arrange(desc(avg)) %>%
  head(n = 20L)
temp3 %>%
  formattable(list(avg = color_bar("orange")), align = 'l')
director_name avg
John Blanchard 9.500
Cary Bell 8.700
Mitchell Altieri 8.700
Sadyk Sher-Niyaz 8.700
Charles Chaplin 8.600
Mike Mayhall 8.600
Damien Chazelle 8.500
Majid Majidi 8.500
Raja Menon 8.500
Ron Fricke 8.500
Sergio Leone 8.475
Christopher Nolan 8.425
Asghar Farhadi 8.400
Bill Melendez 8.400
Catherine Owens 8.400
Jay Oliva 8.400
Marius A. Markevicius 8.400
Moustapha Akkad 8.400
Rakeysh Omprakash Mehra 8.400
Richard Marquand 8.400

Présentation de ggplot2

ggplot2 is an R package for producing statistical, or data, graphics, but it is unlike most other graphics packages because it has a deep underlying grammar.

Hadley Wickman

ggplot2 est un package de visualisation des données souple, facile à appréhender, permettant de produire facilement des graphiques de grande qualité (à la fois informatifs, lisibles et agréables à l’oeil) et le cas échéant de paramétrer à sa guise le rendu de ces graphiques.

Cette présentation se contente d’effleurer les possibilités offertes par ce package. Pour une présentation approfondie, nous renvoyons aux nombreux livres dédiés, dont celui de l’auteur du package, Wickham (2016), dont une version html est accessible librement ici et qui m’a servi de base pour ce tutoriel. Citons également Chang (2012) auquel est associé le package gcookbook regroupant les jeux de données utilisés par l’auteur dans son livre.

La génération de graphiques via ggplot2 repose sur la grammaire des graphiques introduite par Wilkinson (2006) et adapatée et implémentée sous R par Hadley Wickham. Selon lui :

the grammar tells us that a statistical graphic is a mapping from data to aesthetic attributes (colour, shape, size) of geometric objects (points, lines, bars).

Sans rentrer dans les détails de cette grammaire, la terminologie associée présentée ci-dessous (et empruntée à Wickham (2016)) est à connaître.

Terminologie

  • Data ou données : les données que nous souhaitons visualiser, présentées sous la forme d’un data-frame ;
  • aesthetic mappings ou aesthetics : associe les variables du data-frame (ou un sous-ensemble de ces variables) à des attributs graphiques (par exemple, pour un nuage de points, quelle variable est associée à l’axe des abscisses, quelle autre à l’axe des ordonnées, quelle variable sera associée à la taille des points, etc) ;
  • geometric objects : désignent ce que l’on voit sur le graphique : des points, des barres, des courbes, etc ;
  • stats : transformation des données en indicateurs statistiques (dans un sens très large), en vue de leur visualisation ;
  • scales : décrivent la façon dont les aesthetics sont représentés sur le graphique et gèrent l’étiquetage des axes, les boîtes de légende, etc ;
  • coord : un système de coordonnées, typiquement cartésien ;
  • facet : désigne un système de règles décrivant comment les données sont découpées en sous-groupes et comment ces sous-groupes sont représentés.

La fonction qplot

Pour cette introduction, nous allons utiliser le jeu de données diamonds fourni par le package ggplot2

library(ggplot2)
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.29   Premium     I     VS2  62.4    58   334  4.20  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

La fonction qplot permet de générer simplement des graphiques avec ggplot2, dans une syntaxe proche de la fonction de base plot.

qplot(carat, price, data = diamonds)

qplot(log(carat), log(price), data = diamonds)

La syntaxe de cette fonction et les graphiques produits sont proches de la fonction de base. Ceci étant, on peut adjoindre des arguments supplémentaires, tirant partie de la grammaire sur laquelle se base le package. Par exemple, on peut choisir d’attribuer une couleur distincte aux points selon la couleur à la qualité de taille des diamants.

 set.seed(1410)
 dsmall <- diamonds[sample(nrow(diamonds), 100), ]
 qplot(carat, price, data = dsmall, colour = color, shape = cut)

Ainsi, les arguments colour and shape ont fait appel aux aesthetic mappings et scale, dont le rôle a été d’associer à chaque point une couleur et une forme, et d’ajouter les boîtes de légende correspondantes.

La fonction qplot permet de produire d’autres types de graphiques, comme des histogrammes, des diagrammes en barres, diagrammes circulaire, boxplots, etc. Pour cela, on renseignera l’argument geom lors de son appel, qui, comme son nom l’indique, renvoie à la partie geom de la grammaire.

qplot(carat, data = diamonds, geom = "histogram", fill = color)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

qplot(color, data = diamonds, geom = "bar")

qplot(color, price/carat, data = diamonds, geom = "boxplot")

qplot(carat, price, data = diamonds, geom = c("point", "smooth"))
## `geom_smooth()` using method = 'gam'

qplot(color, data = diamonds, geom = "bar", weight = carat) +
scale_y_continuous("carat")

qplot(carat, data = diamonds, ..density..,
      facets = color ~ ., 
      geom = "histogram", 
      binwidth = 0.1, xlim = c(0,3))
## Warning: Removed 32 rows containing non-finite values (stat_bin).

Grammaire et couches

Regardons de plus près la grammaire structurant la création de graphiques par ggplot2 à travers l’exemple suivant.

library('dplyr')
subdata <- filter(diamonds, color %in% c('D', 'E', 'F', 'G'))
head(subdata)
## # 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.22    Fair     E     VS2  65.1    61   337  3.87  3.78  2.49
## 5  0.22 Premium     F     SI1  60.4    61   342  3.88  3.84  2.33
## 6  0.20 Premium     E     SI2  60.2    62   345  3.79  3.75  2.27
qplot(carat, price, data = subdata, facets = color ~ ., geom = c('point', 'smooth'), colour = cut)
## `geom_smooth()` using method = 'gam'

Dans cet exemple, les éléments structurant sont les suivants : * data : les données sont celles du data-frame subdata correspondant à l’extraction des diamants dont la couleur est D, E, F ou G ; * aesthetics : la variable carat est associée à l’axe des abscisses, la variable price, à l’axe des ordonnées, la variable cut à la couleur ; * geoms : il y a deux éléments géométriques superposés (deux couches) : un nuage de points et une courbe de régression avec intervalle de confiance ; * stats : implicitement, il y a un traitement statistique effectué sur les données pour le tracé des courbes de régression ; * facets : on a représenté séparément les éléments géométriques pour chaque couleur ; * scales : plus difficile à identifier ici. On va y revenir…

Enregistrer ce graphique et lui appliquer la fonction summary permet d’avoir un paercçu de ces composantes

my_plot <- qplot(carat, price, data = subdata, facets = color ~ ., geom = c('point', 'smooth'), colour = cut)
summary(my_plot)
## data: carat, cut, color, clarity, depth, table, price, x, y, z
##   [37406x10]
## mapping:  colour = cut, x = carat, y = price
## faceting: <ggproto object: Class FacetGrid, Facet>
##     compute_layout: function
##     draw_back: function
##     draw_front: function
##     draw_labels: function
##     draw_panels: function
##     finish_data: function
##     init_scales: function
##     map: function
##     map_data: function
##     params: list
##     render_back: function
##     render_front: function
##     render_panels: function
##     setup_data: function
##     setup_params: function
##     shrink: TRUE
##     train: function
##     train_positions: function
##     train_scales: function
##     super:  <ggproto object: Class FacetGrid, Facet>
## -----------------------------------
## geom_point: na.rm = FALSE
## stat_identity: na.rm = FALSE
## position_identity 
## 
## geom_smooth: na.rm = FALSE
## stat_smooth: na.rm = FALSE, method = auto, formula = y ~ x, se = TRUE
## position_identity

On peut générer à nouveau ce graphique en décomposant sa construction grâce aux fonctions dédiées.

 ggplot(data = subdata,
        mapping = aes(x = carat, y = price, colour = cut)) +
  geom_point() +
  geom_smooth() +
  facet_grid(color ~ .)
## `geom_smooth()` using method = 'gam'

Ces fonctions offrent une souplesse d’utilisation inexistante avec la fonction qplot.

 ggplot(data = subdata,
        mapping = aes(x = carat, y = price)) +
  geom_point(mapping = aes(colour = cut)) +
  geom_smooth(method = 'lm') +
  facet_grid(color ~ .) +
  theme_light() 

On peut sauvegarder le graphique réalisé pour une utilisation ultérieure dans R. On peut aussi l’exporter en tant qu’image pour l’ajouter à un article, etc.

 my_plot <-  ggplot(data = subdata,
        mapping = aes(x = carat, y = price)) +
  geom_point(mapping = aes(colour = cut)) +
  geom_smooth(method = 'lm') +
  facet_grid(color ~ .) +
  theme_light() 
save(my_plot, file = "essai_ggplot.Rdata")
ggsave(plot = my_plot, filename = "essai_ggplot.png", device = 'png')
## Saving 7 x 5 in image

Chang, Winston. 2012. R Graphics Cookbook: Practical Recipes for Visualizing Data. “ O’Reilly Media, Inc.”

Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer.

Wilkinson, Leland. 2006. The Grammar of Graphics. Springer Science & Business Media.