library(tidyverse)
10 Manipuler les données avec dplyr
dplyr
est une extension facilitant le traitement et la manipulation de données contenues dans une ou plusieurs tables. Elle propose une syntaxe claire et cohérente, sous formes de verbes, pour la plupart des opérations de ce type.
dplyr
part du principe que les données sont organisées selon le modèle des tidy data (voir Section 6.3). Les fonctions de l’extension peuvent s’appliquer à des tableaux de type data.frame
ou tibble
, et elles retournent systématiquement un tibble
(voir Section 6.4).
Le code présent dans ce document nécessite d’avoir installé la version 1.0 de dplyr
(ou plus récente).
10.1 Préparation
dplyr
fait partie du coeur du tidyverse, elle est donc chargée automatiquement avec :
On peut également la charger individuellement.
library(dplyr)
Dans ce qui suit on va utiliser le jeu de données nycflights13
, contenu dans l’extension du même nom (qu’il faut donc avoir installé). Celui-ci correspond aux données de tous les vols au départ d’un des trois aéroports de New-York en 2013. Il a la particularité d’être réparti en trois tables :
flights
contient des informations sur les vols : date, départ, destination, horaires, retard…airports
contient des informations sur les aéroportsairlines
contient des données sur les compagnies aériennes
On va charger les trois tables du jeu de données :
library(nycflights13)
## Chargement des trois tables
data(flights)
data(airports)
data(airlines)
Trois objets correspondant aux trois tables ont dû apparaître dans votre environnement.
10.2 Les verbes de dplyr
La manipulation de données avec dplyr
se fait en utilisant un nombre réduit de verbes, qui correspondent chacun à une action différente appliquée à un tableau de données.
10.2.1 slice
Le verbe slice
sélectionne des lignes du tableau selon leur position. On lui passe un chiffre ou un vecteur de chiffres.
Si on souhaite sélectionner la 345e ligne du tableau airports
:
slice(airports, 345)
#> # A tibble: 1 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 CYF Chefornak Airport 60.1 -164. 40 -9 A America/Anchorage
Si on veut sélectionner les 5 premières lignes :
slice(airports, 1:5)
#> # A tibble: 5 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A America/New…
#> 2 06A Moton Field Municipal Airport 32.5 -85.7 264 -6 A America/Chi…
#> 3 06C Schaumburg Regional 42.0 -88.1 801 -6 A America/Chi…
#> 4 06N Randall Airport 41.4 -74.4 523 -5 A America/New…
#> 5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A America/New…
slice
propose plusieurs variantes utiles, dont slice_head
et slice_tail
, qui permettent de sélectionner les premières ou les dernières lignes du tableau (on peut spécifier le nombre de lignes souhaitées avec n
, ou la proportion avec prop
).
slice_tail(airports, n = 3)
#> # A tibble: 3 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 ZWI Wilmington Amtrak Station 39.7 -75.6 0 -5 A America/New_York
#> 2 ZWU Washington Union Station 38.9 -77.0 76 -5 A America/New_York
#> 3 ZYP Penn Station 40.8 -74.0 35 -5 A America/New_York
slice_head(airlines, prop = 0.2)
#> # A tibble: 3 × 2
#> carrier name
#> <chr> <chr>
#> 1 9E Endeavor Air Inc.
#> 2 AA American Airlines Inc.
#> 3 AS Alaska Airlines Inc.
Autres variantes utiles, slice_min
et slice_max
permettent de sélectionner les lignes avec les valeurs les plus grandes ou les plus petite d’une variable donnée. Ainsi, la commande suivante sélectionne le vol ayant le retard au départ le plus faible.
slice_min(flights, dep_delay)
#> # A tibble: 1 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 12 7 2040 2123 -43 40 2352
#> # ℹ 11 more variables: 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 aussi spécifier le nombre de lignes souhaitées, par exemple la commande suivante retourne les 5 aéroports avec l’altitude la plus élevée (en cas de valeurs ex-aequo, il se peut que le nombre de lignes retournées soit plus élevé que celui demandé).
slice_max(airports, alt, n = 5)
#> # A tibble: 5 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 TEX Telluride 38.0 -108. 9078 -7 A America/D…
#> 2 TVL Lake Tahoe Airport 38.9 -120. 8544 -8 A America/L…
#> 3 ASE Aspen Pitkin County Sardy Field 39.2 -107. 7820 -7 A America/D…
#> 4 GUC Gunnison - Crested Butte 38.5 -107. 7678 -7 A America/D…
#> 5 BCE Bryce Canyon 37.7 -112. 7590 -7 A America/D…
10.2.2 filter
filter
sélectionne des lignes d’une table selon une condition. On lui passe en paramètre un test, et seules les lignes pour lesquelles ce test renvoie TRUE
(vrai) sont conservées. Pour plus d’informations sur les tests et leur syntaxe, voir Section 9.2.
Par exemple, si on veut sélectionner les vols du mois de janvier, on peut filtrer sur la variable month
de la manière suivante :
filter(flights, month == 1)
#> # A tibble: 27,004 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> 7 2013 1 1 555 600 -5 913 854
#> 8 2013 1 1 557 600 -3 709 723
#> 9 2013 1 1 557 600 -3 838 846
#> 10 2013 1 1 558 600 -2 753 745
#> # ℹ 26,994 more rows
#> # ℹ 11 more variables: 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>
Si on veut uniquement les vols avec un retard au départ (variable dep_delay
) compris entre 10 et 15 minutes :
filter(flights, dep_delay >= 10 & dep_delay <= 15)
#> # A tibble: 14,919 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 611 600 11 945 931
#> 2 2013 1 1 623 610 13 920 915
#> 3 2013 1 1 743 730 13 1107 1100
#> 4 2013 1 1 743 730 13 1059 1056
#> 5 2013 1 1 851 840 11 1215 1206
#> 6 2013 1 1 912 900 12 1241 1220
#> 7 2013 1 1 914 900 14 1058 1043
#> 8 2013 1 1 920 905 15 1039 1025
#> 9 2013 1 1 1011 1001 10 1133 1128
#> 10 2013 1 1 1112 1100 12 1440 1438
#> # ℹ 14,909 more rows
#> # ℹ 11 more variables: 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>
Si on passe plusieurs arguments à filter
, celui-ci rajoute automatiquement une condition et entre les conditions. La commande précédente peut donc être écrite de la manière suivante, avec le même résultat :
filter(flights, dep_delay >= 10, dep_delay <= 15)
On peut également placer des fonctions dans les tests, qui nous permettent par exemple de sélectionner les vols ayant une distance supérieure à la distance médiane :
filter(flights, distance > median(distance))
#> # A tibble: 167,133 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 555 600 -5 913 854
#> 6 2013 1 1 557 600 -3 838 846
#> 7 2013 1 1 558 600 -2 849 851
#> 8 2013 1 1 558 600 -2 853 856
#> 9 2013 1 1 558 600 -2 924 917
#> 10 2013 1 1 558 600 -2 923 937
#> # ℹ 167,123 more rows
#> # ℹ 11 more variables: 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>
10.2.3 select
et rename
select
permet de sélectionner des colonnes d’un tableau de données. Ainsi, si on veut extraire les colonnes lat
et lon
du tableau airports :
select(airports, lat, lon)
#> # A tibble: 1,458 × 2
#> lat lon
#> <dbl> <dbl>
#> 1 41.1 -80.6
#> 2 32.5 -85.7
#> 3 42.0 -88.1
#> 4 41.4 -74.4
#> 5 31.1 -81.4
#> 6 36.4 -82.2
#> 7 41.5 -84.5
#> 8 42.9 -76.8
#> 9 39.8 -76.6
#> 10 48.1 -123.
#> # ℹ 1,448 more rows
Si on fait précéder le nom d’un -
, la colonne est éliminée plutôt que sélectionnée :
select(airports, -lat, -lon)
#> # A tibble: 1,458 × 6
#> faa name alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <chr> <chr>
#> 1 04G Lansdowne Airport 1044 -5 A America/New_York
#> 2 06A Moton Field Municipal Airport 264 -6 A America/Chicago
#> 3 06C Schaumburg Regional 801 -6 A America/Chicago
#> 4 06N Randall Airport 523 -5 A America/New_York
#> 5 09J Jekyll Island Airport 11 -5 A America/New_York
#> 6 0A9 Elizabethton Municipal Airport 1593 -5 A America/New_York
#> 7 0G6 Williams County Airport 730 -5 A America/New_York
#> 8 0G7 Finger Lakes Regional Airport 492 -5 A America/New_York
#> 9 0P2 Shoestring Aviation Airfield 1000 -5 U America/New_York
#> 10 0S9 Jefferson County Intl 108 -8 A America/Los_Angeles
#> # ℹ 1,448 more rows
select
comprend toute une série de fonctions facilitant la sélection de colonnes multiples. Par exemple, starts_with
, ends_width
, contains
ou matches
permettent d’exprimer des conditions sur les noms de variables.
select(flights, starts_with("dep_"))
#> # A tibble: 336,776 × 2
#> dep_time dep_delay
#> <int> <dbl>
#> 1 517 2
#> 2 533 4
#> 3 542 2
#> 4 544 -1
#> 5 554 -6
#> 6 554 -4
#> 7 555 -5
#> 8 557 -3
#> 9 557 -3
#> 10 558 -2
#> # ℹ 336,766 more rows
La syntaxe colonne1:colonne2
permet de sélectionner toutes les colonnes situées entre colonne1
et colonne2
incluses1.
select(flights, year:day)
#> # A tibble: 336,776 × 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
#> # ℹ 336,766 more rows
select
propose de nombreuses autres possibilités de sélection qui sont décrites dans la documentation de l’extension tidyselect
.
Une variante de select
est rename
2, qui permet de renommer des colonnes. On l’utilise en lui passant des paramètres de la forme nouveau_nom = ancien_nom
. Ainsi, si on veut renommer les colonnes lon
et lat
de airports
en longitude
et latitude
:
rename(airports, longitude = lon, latitude = lat)
#> # A tibble: 1,458 × 8
#> faa name latitude longitude alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A Amer…
#> 2 06A Moton Field Municipal Airpo… 32.5 -85.7 264 -6 A Amer…
#> 3 06C Schaumburg Regional 42.0 -88.1 801 -6 A Amer…
#> 4 06N Randall Airport 41.4 -74.4 523 -5 A Amer…
#> 5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A Amer…
#> 6 0A9 Elizabethton Municipal Airp… 36.4 -82.2 1593 -5 A Amer…
#> 7 0G6 Williams County Airport 41.5 -84.5 730 -5 A Amer…
#> 8 0G7 Finger Lakes Regional Airpo… 42.9 -76.8 492 -5 A Amer…
#> 9 0P2 Shoestring Aviation Airfield 39.8 -76.6 1000 -5 U Amer…
#> 10 0S9 Jefferson County Intl 48.1 -123. 108 -8 A Amer…
#> # ℹ 1,448 more rows
Si les noms de colonnes comportent des espaces ou des caractères spéciaux, on peut les entourer de guillemets ("
) ou de quotes inverses (`
) :
<- rename(
tmp
flights,"retard départ" = dep_delay,
"retard arrivée" = arr_delay
)select(tmp, `retard départ`, `retard arrivée`)
#> # A tibble: 336,776 × 2
#> `retard départ` `retard arrivée`
#> <dbl> <dbl>
#> 1 2 11
#> 2 4 20
#> 3 2 33
#> 4 -1 -18
#> 5 -6 -25
#> 6 -4 12
#> 7 -5 19
#> 8 -3 -14
#> 9 -3 -8
#> 10 -2 8
#> # ℹ 336,766 more rows
10.2.4 arrange
arrange
réordonne les lignes d’un tableau selon une ou plusieurs colonnes.
Ainsi, si on veut trier le tableau flights
selon le retard au départ croissant :
arrange(flights, dep_delay)
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 12 7 2040 2123 -43 40 2352
#> 2 2013 2 3 2022 2055 -33 2240 2338
#> 3 2013 11 10 1408 1440 -32 1549 1559
#> 4 2013 1 11 1900 1930 -30 2233 2243
#> 5 2013 1 29 1703 1730 -27 1947 1957
#> 6 2013 8 9 729 755 -26 1002 955
#> 7 2013 10 23 1907 1932 -25 2143 2143
#> 8 2013 3 30 2030 2055 -25 2213 2250
#> 9 2013 3 2 1431 1455 -24 1601 1631
#> 10 2013 5 5 934 958 -24 1225 1309
#> # ℹ 336,766 more rows
#> # ℹ 11 more variables: 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 trier selon plusieurs colonnes. Par exemple selon le mois, puis selon le retard au départ :
arrange(flights, month, dep_delay)
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 11 1900 1930 -30 2233 2243
#> 2 2013 1 29 1703 1730 -27 1947 1957
#> 3 2013 1 12 1354 1416 -22 1606 1650
#> 4 2013 1 21 2137 2159 -22 2232 2316
#> 5 2013 1 20 704 725 -21 1025 1035
#> 6 2013 1 12 2050 2110 -20 2310 2355
#> 7 2013 1 12 2134 2154 -20 4 50
#> 8 2013 1 14 2050 2110 -20 2329 2355
#> 9 2013 1 4 2140 2159 -19 2241 2316
#> 10 2013 1 11 1947 2005 -18 2209 2230
#> # ℹ 336,766 more rows
#> # ℹ 11 more variables: 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>
Si on veut trier selon une colonne par ordre décroissant, on lui applique la fonction desc()
:
arrange(flights, desc(dep_delay))
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 6 15 1432 1935 1137 1607 2120
#> 3 2013 1 10 1121 1635 1126 1239 1810
#> 4 2013 9 20 1139 1845 1014 1457 2210
#> 5 2013 7 22 845 1600 1005 1044 1815
#> 6 2013 4 10 1100 1900 960 1342 2211
#> 7 2013 3 17 2321 810 911 135 1020
#> 8 2013 6 27 959 1900 899 1236 2226
#> 9 2013 7 22 2257 759 898 121 1026
#> 10 2013 12 5 756 1700 896 1058 2020
#> # ℹ 336,766 more rows
#> # ℹ 11 more variables: 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>
Combiné avec slice
, arrange
permet par exemple de sélectionner les trois vols ayant eu le plus de retard :
<- arrange(flights, desc(dep_delay))
tmp slice(tmp, 1:3)
#> # A tibble: 3 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 6 15 1432 1935 1137 1607 2120
#> 3 2013 1 10 1121 1635 1126 1239 1810
#> # ℹ 11 more variables: 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>
10.2.5 mutate
mutate
permet de créer de nouvelles colonnes dans le tableau de données, en général à partir de variables existantes.
Par exemple, la table flights
contient la durée du vol en minutes.. Si on veut créer une nouvelle variable duree_h
avec cette durée en heures, on peut faire :
<- mutate(flights, duree_h = air_time / 60)
flights
select(flights, air_time, duree_h)
#> # A tibble: 336,776 × 2
#> air_time duree_h
#> <dbl> <dbl>
#> 1 227 3.78
#> 2 227 3.78
#> 3 160 2.67
#> 4 183 3.05
#> 5 116 1.93
#> 6 150 2.5
#> 7 158 2.63
#> 8 53 0.883
#> 9 140 2.33
#> 10 138 2.3
#> # ℹ 336,766 more rows
On peut créer plusieurs nouvelles colonnes en une seule commande, et les expressions successives peuvent prendre en compte les résultats des calculs précédents. L’exemple suivant convertit d’abord la durée en heures dans une variable duree_h
et la distance en kilomètres dans une variable distance_km
, puis utilise ces nouvelles colonnes pour calculer la vitesse en km/h.
<- mutate(
flights
flights,duree_h = air_time / 60,
distance_km = distance / 0.62137,
vitesse = distance_km / duree_h
)
select(flights, air_time, duree_h, distance, distance_km, vitesse)
#> # A tibble: 336,776 × 5
#> air_time duree_h distance distance_km vitesse
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 227 3.78 1400 2253. 596.
#> 2 227 3.78 1416 2279. 602.
#> 3 160 2.67 1089 1753. 657.
#> 4 183 3.05 1576 2536. 832.
#> 5 116 1.93 762 1226. 634.
#> 6 150 2.5 719 1157. 463.
#> 7 158 2.63 1065 1714. 651.
#> 8 53 0.883 229 369. 417.
#> 9 140 2.33 944 1519. 651.
#> 10 138 2.3 733 1180. 513.
#> # ℹ 336,766 more rows
À noter que mutate
est évidemment parfaitement compatible avec les fonctions vues Chapitre 9 sur les recodages : fct_recode
, ifelse
, case_when
…
L’avantage d’utiliser mutate
est double. D’abord il permet d’éviter d’avoir à saisir le nom du tableau de données dans les conditions d’un ifelse
ou d’un case_when
:
<- mutate(
flights
flights,type_retard = case_when(
> 0 & arr_delay > 0 ~ "Retard départ et arrivée",
dep_delay > 0 & arr_delay <= 0 ~ "Retard départ",
dep_delay <= 0 & arr_delay > 0 ~ "Retard arrivée",
dep_delay TRUE ~ "Aucun retard"
) )
Ensuite, il permet aussi d’intégrer ces recodages dans un pipeline de traitement de données, concept présenté dans la section suivante.
10.3 Enchaîner les opérations avec le pipe
Quand on manipule un tableau de données, il est très fréquent d’enchaîner plusieurs opérations. On va par exemple extraire une sous-population avec filter
, sélectionner des colonnes avec select
puis trier selon une variable avec arrange
, etc.
Quand on veut enchaîner des opérations, on peut le faire de différentes manières. La première est d’effectuer toutes les opérations en une fois en les “emboîtant” :
arrange(select(filter(flights, dest == "LAX"), dep_delay, arr_delay), dep_delay)
Cette notation a plusieurs inconvénients :
- elle est peu lisible
- les opérations apparaissent dans l’ordre inverse de leur réalisation. Ici on effectue d’abord le
filter
, puis leselect
, puis learrange
, alors qu’à la lecture du code c’est learrange
qui apparaît en premier. - Il est difficile de voir quel paramètre se rapporte à quelle fonction
Une autre manière de faire est d’effectuer les opérations les unes après les autres, en stockant les résultats intermédiaires dans un objet temporaire :
<- filter(flights, dest == "LAX")
tmp <- select(tmp, dep_delay, arr_delay)
tmp arrange(tmp, dep_delay)
C’est nettement plus lisible, l’ordre des opérations est le bon, et les paramètres sont bien rattachés à leur fonction. Par contre, ça reste un peu “verbeux”, et on crée un objet temporaire tmp
dont on n’a pas réellement besoin.
Pour simplifier et améliorer encore la lisibilité du code, on va utiliser un nouvel opérateur, baptisé pipe3. Le pipe se note %>%
, et son fonctionnement est le suivant : si j’exécute expr %>% f
, alors le résultat de l’expression expr
, à gauche du pipe, sera passé comme premier argument à la fonction f
, à droite du pipe, ce qui revient à exécuter f(expr)
.
Ainsi les deux expressions suivantes sont rigoureusement équivalentes :
filter(flights, dest == "LAX")
%>% filter(dest == "LAX") flights
Ce qui est particulièrement intéressant, c’est qu’on va pouvoir enchaîner les pipes. Plutôt que d’écrire :
select(filter(flights, dest == "LAX"), dep_delay, arr_delay)
On va pouvoir faire :
%>% filter(dest == "LAX") %>% select(dep_delay, arr_delay) flights
À chaque fois, le résultat de ce qui se trouve à gauche du pipe est passé comme premier argument à ce qui se trouve à droite : on part de l’objet flights
, qu’on passe comme premier argument à la fonction filter
, puis on passe le résultat de ce filter
comme premier argument du select
.
Le résultat final est le même avec les deux syntaxes, mais avec le pipe l’ordre des opérations correspond à l’ordre naturel de leur exécution, et on n’a pas eu besoin de créer d’objet intermédiaire.
Si la liste des fonctions enchaînées est longue, on peut les répartir sur plusieurs lignes à condition que l’opérateur %>%
soit en fin de ligne :
%>%
flights filter(dest == "LAX") %>%
select(dep_delay, arr_delay) %>%
arrange(dep_delay)
On appelle une suite d’instructions de ce type un pipeline.
Évidemment, il est naturel de vouloir récupérer le résultat final d’un pipeline pour le stocker dans un objet. On peut stocker le résultat du pipeline ci-dessus dans un nouveau tableau delay_la
de la manière suivante :
<- flights %>%
delay_la filter(dest == "LAX") %>%
select(dep_delay, arr_delay) %>%
arrange(dep_delay)
Dans ce cas, delay_la
contiendra le tableau final, obtenu après application des trois instructions filter
, select
et arrange
.
Cette notation n’est pas forcément très intuitive au départ : il faut bien comprendre que c’est le résultat final, une fois application de toutes les opérations du pipeline, qui est renvoyé et stocké dans l’objet en début de ligne.
Une manière de le comprendre peut être de voir que la notation suivante :
<- flights %>%
delay_la filter(dest == "LAX") %>%
select(dep_delay, arr_delay)
est équivalente à :
<- (flights %>% filter(dest == "LAX") %>% select(dep_delay, arr_delay)) delay_la
L’utilisation du pipe n’est pas obligatoire, mais elle rend les scripts plus lisibles et plus rapides à saisir. On l’utilisera donc dans ce qui suit.
Depuis la version 4.1, R propose un pipe “natif”, qui fonctionne partout, même si on n’utilise pas les extensions du tidyverse. Celui-ci est noté |>
.
Il s’utilise de la même manière que %>%
:
flights |> filter(dest == "LAX")
Ce pipe natif est à la fois un peu plus rapide et un peu moins souple. Par exemple, il est possible avec %>%
d’appeler une fonction sans mettre de parenthèses :
df %>% View
Ce n’est pas possible d’omettre les parenthèses avec |>
, on doit obligatoirement faire :
df |> View()
Dans la suite de ce document on privilégiera (pour l’instant) le pipe du tidyverse %>%
, pour des raisons de compatibilité avec des versions de R moins récentes.
10.4 Opérations groupées
10.4.1 group_by
Un élément très important de dplyr
est la fonction group_by
. Elle permet de définir des groupes de lignes à partir des valeurs d’une ou plusieurs colonnes. Par exemple, on peut grouper les vols selon leur mois :
%>% group_by(month)
flights #> # A tibble: 336,776 × 22
#> # Groups: month [12]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> 7 2013 1 1 555 600 -5 913 854
#> 8 2013 1 1 557 600 -3 709 723
#> 9 2013 1 1 557 600 -3 838 846
#> 10 2013 1 1 558 600 -2 753 745
#> # ℹ 336,766 more rows
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
Par défaut ceci ne fait rien de visible, à part l’apparition d’une mention Groups
dans l’affichage du résultat. Mais à partir du moment où des groupes ont été définis, les verbes comme slice
, mutate
ou summarise
vont en tenir compte lors de leurs opérations.
Par exemple, si on applique slice
à un tableau préalablement groupé, il va sélectionner les lignes aux positions indiquées pour chaque groupe. Ainsi la commande suivante affiche le premier vol de chaque mois, selon leur ordre d’apparition dans le tableau :
%>% group_by(month) %>% slice(1)
flights #> # A tibble: 12 × 22
#> # Groups: month [12]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 2 1 456 500 -4 652 648
#> 3 2013 3 1 4 2159 125 318 56
#> 4 2013 4 1 454 500 -6 636 640
#> 5 2013 5 1 9 1655 434 308 2020
#> 6 2013 6 1 2 2359 3 341 350
#> 7 2013 7 1 1 2029 212 236 2359
#> 8 2013 8 1 12 2130 162 257 14
#> 9 2013 9 1 9 2359 10 343 340
#> 10 2013 10 1 447 500 -13 614 648
#> 11 2013 11 1 5 2359 6 352 345
#> 12 2013 12 1 13 2359 14 446 445
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
Plus utile, en utilisant une variante comme slice_min
ou slice_max
, on peut sélectionner les lignes ayant les valeurs les plus grandes ou les plus petites pour chaque groupe. Par exemple la commande suivant sélectionne, pour chaque mois de l’année, le vol ayant eu le retard le plus important.
%>% group_by(month) %>% slice_max(dep_delay)
flights #> # A tibble: 12 × 22
#> # Groups: month [12]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 2 10 2243 830 853 100 1106
#> 3 2013 3 17 2321 810 911 135 1020
#> 4 2013 4 10 1100 1900 960 1342 2211
#> 5 2013 5 3 1133 2055 878 1250 2215
#> 6 2013 6 15 1432 1935 1137 1607 2120
#> 7 2013 7 22 845 1600 1005 1044 1815
#> 8 2013 8 8 2334 1454 520 120 1710
#> 9 2013 9 20 1139 1845 1014 1457 2210
#> 10 2013 10 14 2042 900 702 2255 1127
#> 11 2013 11 3 603 1645 798 829 1913
#> 12 2013 12 5 756 1700 896 1058 2020
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
Idem pour mutate
: les opérations appliquées lors du calcul des valeurs des nouvelles colonnes sont appliquées groupe de lignes par groupe de lignes. Dans l’exemple suivant, on ajoute une nouvelle colonne qui contient le retard moyen pour chaque compagnie aérienne. Cette valeur est donc différente d’une compagnie à une autre, mais identique pour tous les vols d’une même compagnie :
%>%
flights group_by(carrier) %>%
mutate(mean_delay_carrier = mean(dep_delay, na.rm = TRUE)) %>%
select(dep_delay, mean_delay_carrier)
#> Adding missing grouping variables: `carrier`
#> # A tibble: 336,776 × 3
#> # Groups: carrier [16]
#> carrier dep_delay mean_delay_carrier
#> <chr> <dbl> <dbl>
#> 1 UA 2 12.1
#> 2 UA 4 12.1
#> 3 AA 2 8.59
#> 4 B6 -1 13.0
#> 5 DL -6 9.26
#> 6 UA -4 12.1
#> 7 B6 -5 13.0
#> 8 EV -3 20.0
#> 9 B6 -3 13.0
#> 10 AA -2 8.59
#> # ℹ 336,766 more rows
Ceci peut permettre, par exemple, de déterminer si un retard donné est supérieur ou inférieur au retard médian de la compagnie :
%>%
flights group_by(carrier) %>%
mutate(
median_delay = median(dep_delay, na.rm = TRUE),
delay_carrier = ifelse(
> median_delay,
dep_delay "Supérieur",
"Inférieur ou égal"
)%>%
) select(dep_delay, median_delay, delay_carrier)
#> Adding missing grouping variables: `carrier`
#> # A tibble: 336,776 × 4
#> # Groups: carrier [16]
#> carrier dep_delay median_delay delay_carrier
#> <chr> <dbl> <dbl> <chr>
#> 1 UA 2 0 Supérieur
#> 2 UA 4 0 Supérieur
#> 3 AA 2 -3 Supérieur
#> 4 B6 -1 -1 Inférieur ou égal
#> 5 DL -6 -2 Inférieur ou égal
#> 6 UA -4 0 Inférieur ou égal
#> 7 B6 -5 -1 Inférieur ou égal
#> 8 EV -3 -1 Inférieur ou égal
#> 9 B6 -3 -1 Inférieur ou égal
#> 10 AA -2 -3 Supérieur
#> # ℹ 336,766 more rows
group_by
peut aussi être utile avec filter
, par exemple pour sélectionner pour chaque mois les vols avec un retard au départ plus élevé que le retard moyen ce mois-ci.
%>%
flights group_by(month) %>%
filter(dep_delay >= mean(dep_delay, na.rm = TRUE))
#> # A tibble: 78,164 × 22
#> # Groups: month [12]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 611 600 11 945 931
#> 2 2013 1 1 623 610 13 920 915
#> 3 2013 1 1 632 608 24 740 728
#> 4 2013 1 1 732 645 47 1011 941
#> 5 2013 1 1 743 730 13 1107 1100
#> 6 2013 1 1 743 730 13 1059 1056
#> 7 2013 1 1 749 710 39 939 850
#> 8 2013 1 1 811 630 101 1047 830
#> 9 2013 1 1 826 715 71 1136 1045
#> 10 2013 1 1 848 1835 853 1001 1950
#> # ℹ 78,154 more rows
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
Attention : la clause group_by
marche pour les verbes déjà vus précédemment, sauf pour arrange
, qui par défaut trie la table sans tenir compte des groupes. Pour obtenir un tri par groupe, il faut lui ajouter l’argument .by_group = TRUE
.
On peut voir la différence en comparant les deux résultats suivants :
%>%
flights group_by(month) %>%
arrange(desc(dep_delay))
#> # A tibble: 336,776 × 22
#> # Groups: month [12]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 6 15 1432 1935 1137 1607 2120
#> 3 2013 1 10 1121 1635 1126 1239 1810
#> 4 2013 9 20 1139 1845 1014 1457 2210
#> 5 2013 7 22 845 1600 1005 1044 1815
#> 6 2013 4 10 1100 1900 960 1342 2211
#> 7 2013 3 17 2321 810 911 135 1020
#> 8 2013 6 27 959 1900 899 1236 2226
#> 9 2013 7 22 2257 759 898 121 1026
#> 10 2013 12 5 756 1700 896 1058 2020
#> # ℹ 336,766 more rows
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
%>%
flights group_by(month) %>%
arrange(desc(dep_delay), .by_group = TRUE)
#> # A tibble: 336,776 × 22
#> # Groups: month [12]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 1 10 1121 1635 1126 1239 1810
#> 3 2013 1 1 848 1835 853 1001 1950
#> 4 2013 1 13 1809 810 599 2054 1042
#> 5 2013 1 16 1622 800 502 1911 1054
#> 6 2013 1 23 1551 753 478 1812 1006
#> 7 2013 1 10 1525 900 385 1713 1039
#> 8 2013 1 1 2343 1724 379 314 1938
#> 9 2013 1 2 2131 1512 379 2340 1741
#> 10 2013 1 7 2021 1415 366 2332 1724
#> # ℹ 336,766 more rows
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
10.4.2 summarise
et count
summarise
permet d’agréger les lignes du tableau en effectuant une opération “résumée” sur une ou plusieurs colonnes. Par exemple, si on souhaite connaître les retards moyens au départ et à l’arrivée pour l’ensemble des vols du tableau flights
:
%>%
flights summarise(
retard_dep = mean(dep_delay, na.rm = TRUE),
retard_arr = mean(arr_delay, na.rm = TRUE)
)#> # A tibble: 1 × 2
#> retard_dep retard_arr
#> <dbl> <dbl>
#> 1 12.6 6.90
Cette fonction est en général utilisée avec group_by
, puisqu’elle permet du coup d’agréger et résumer les lignes du tableau groupe par groupe. Si on souhaite calculer le délai maximum, le délai minimum et le délai moyen au départ pour chaque mois, on pourra faire :
%>%
flights group_by(month) %>%
summarise(
max_delay = max(dep_delay, na.rm = TRUE),
min_delay = min(dep_delay, na.rm = TRUE),
mean_delay = mean(dep_delay, na.rm = TRUE)
)#> # A tibble: 12 × 4
#> month max_delay min_delay mean_delay
#> <int> <dbl> <dbl> <dbl>
#> 1 1 1301 -30 10.0
#> 2 2 853 -33 10.8
#> 3 3 911 -25 13.2
#> 4 4 960 -21 13.9
#> 5 5 878 -24 13.0
#> 6 6 1137 -21 20.8
#> 7 7 1005 -22 21.7
#> 8 8 520 -26 12.6
#> 9 9 1014 -24 6.72
#> 10 10 702 -25 6.24
#> 11 11 798 -32 5.44
#> 12 12 896 -43 16.6
summarise
dispose d’un opérateur spécial, n()
, qui retourne le nombre de lignes du groupe. Ainsi si on veut le nombre de vols par destination, on peut utiliser :
%>%
flights group_by(dest) %>%
summarise(nb = n())
#> # A tibble: 105 × 2
#> dest nb
#> <chr> <int>
#> 1 ABQ 254
#> 2 ACK 265
#> 3 ALB 439
#> 4 ANC 8
#> 5 ATL 17215
#> 6 AUS 2439
#> 7 AVL 275
#> 8 BDL 443
#> 9 BGR 375
#> 10 BHM 297
#> # ℹ 95 more rows
n()
peut aussi être utilisée avec filter
et mutate
.
À noter que quand on veut compter le nombre de lignes par groupe, il est plus simple d’utiliser directement la fonction count
. Ainsi le code suivant est identique au précédent :
%>%
flights count(dest)
#> # A tibble: 105 × 2
#> dest n
#> <chr> <int>
#> 1 ABQ 254
#> 2 ACK 265
#> 3 ALB 439
#> 4 ANC 8
#> 5 ATL 17215
#> 6 AUS 2439
#> 7 AVL 275
#> 8 BDL 443
#> 9 BGR 375
#> 10 BHM 297
#> # ℹ 95 more rows
10.4.3 Grouper selon plusieurs variables
On peut grouper selon plusieurs variables à la fois, il suffit de les indiquer dans la clause du group_by
. Le pipeline suivant calcule le retard moyen au départ pour chaque mois et pour chaque destination, et trie le résultat par retard décroissant :
%>%
flights group_by(month, dest) %>%
summarise(retard_moyen = mean(dep_delay, na.rm = TRUE)) %>%
arrange(desc(retard_moyen))
#> `summarise()` has grouped output by 'month'. You can override using the
#> `.groups` argument.
#> # A tibble: 1,113 × 3
#> # Groups: month [12]
#> month dest retard_moyen
#> <int> <chr> <dbl>
#> 1 12 BZN 75
#> 2 7 TUL 72.6
#> 3 3 DSM 71.0
#> 4 7 CAE 69.4
#> 5 11 SBN 67.5
#> 6 7 BHM 64.6
#> 7 7 TYS 60.6
#> 8 6 BHM 57.2
#> 9 1 TUL 55.2
#> 10 1 SAV 54.8
#> # ℹ 1,103 more rows
On peut également utiliser count
sur plusieurs variables. Les commandes suivantes comptent le nombre de vols pour chaque couple aéroport de départ / aéroport d’arrivée, et trie le résultat par nombre de vols décroissant. Ici la colonne qui contient le nombre de vols, créée par count
, s’appelle n
par défaut :
%>%
flights count(origin, dest) %>%
arrange(desc(n))
#> # A tibble: 224 × 3
#> origin dest n
#> <chr> <chr> <int>
#> 1 JFK LAX 11262
#> 2 LGA ATL 10263
#> 3 LGA ORD 8857
#> 4 JFK SFO 8204
#> 5 LGA CLT 6168
#> 6 EWR ORD 6100
#> 7 JFK BOS 5898
#> 8 LGA MIA 5781
#> 9 JFK MCO 5464
#> 10 EWR BOS 5327
#> # ℹ 214 more rows
On peut utiliser plusieurs opérations de groupage dans le même pipeline. Ainsi, si on souhaite déterminer le couple aéroport de départ / aéroport d’arrivée ayant le retard moyen au départ le plus élevé pour chaque mois de l’année, on devra procéder en deux étapes :
- d’abord grouper selon mois, aéroports d’origine et d’arrivée pour calculer le retard moyen
- puis grouper uniquement selon le mois pour sélectionner le mois avec le retard moyen maximal.
Au final, on obtient le code suivant :
%>%
flights group_by(month, origin, dest) %>%
summarise(retard_moyen = mean(dep_delay, na.rm = TRUE)) %>%
group_by(month) %>%
slice_max(retard_moyen)
#> `summarise()` has grouped output by 'month', 'origin'. You can override using
#> the `.groups` argument.
#> # A tibble: 12 × 4
#> # Groups: month [12]
#> month origin dest retard_moyen
#> <int> <chr> <chr> <dbl>
#> 1 1 EWR TUL 55.2
#> 2 2 EWR DSM 48.6
#> 3 3 EWR DSM 71.0
#> 4 4 EWR OKC 47.0
#> 5 5 EWR TYS 60.6
#> 6 6 EWR TYS 68.2
#> 7 7 EWR CAE 81.5
#> 8 8 LGA GSO 50.1
#> 9 9 LGA MSN 24.7
#> 10 10 EWR CAE 50.1
#> 11 11 LGA SBN 67.5
#> 12 12 EWR BZN 75
10.4.4 Dégroupage
Lorsqu’on effectue un group_by
suivi d’un summarise
, le tableau résultat est automatiquement dégroupé de la dernière variable de regroupement. Ainsi le tableau généré par le code suivant est seulement groupé par month
et origin
:
%>%
flights group_by(month, origin, dest) %>%
summarise(retard_moyen = mean(dep_delay, na.rm = TRUE))
#> `summarise()` has grouped output by 'month', 'origin'. You can override using
#> the `.groups` argument.
#> # A tibble: 2,313 × 4
#> # Groups: month, origin [36]
#> month origin dest retard_moyen
#> <int> <chr> <chr> <dbl>
#> 1 1 EWR ALB 41.4
#> 2 1 EWR ATL 8.07
#> 3 1 EWR AUS 6.67
#> 4 1 EWR AVL 25.5
#> 5 1 EWR BDL 21.1
#> 6 1 EWR BNA 16.3
#> 7 1 EWR BOS 8.99
#> 8 1 EWR BQN 12.3
#> 9 1 EWR BTV 20.5
#> 10 1 EWR BUF 23.1
#> # ℹ 2,303 more rows
dplyr
nous le signale d’ailleurs via un message d’avertissement : summarise() has grouped output by 'month', 'origin'
.
Ce dégroupage progressif peut permettre “d’enchaîner” les opérations groupées. Dans l’exemple suivant on calcule le retard moyen au départ par destination et on conserve les trois retards les plus importants pour chaque mois.
%>%
flights group_by(month, dest) %>%
summarise(retard_moyen = mean(dep_delay, na.rm = TRUE)) %>%
slice_max(retard_moyen, n = 3)
#> `summarise()` has grouped output by 'month'. You can override using the
#> `.groups` argument.
#> # A tibble: 36 × 3
#> # Groups: month [12]
#> month dest retard_moyen
#> <int> <chr> <dbl>
#> 1 1 TUL 55.2
#> 2 1 SAV 54.8
#> 3 1 DSM 42.2
#> 4 2 DSM 48.6
#> 5 2 TUL 34.2
#> 6 2 GSP 32.4
#> 7 3 DSM 71.0
#> 8 3 PVD 47.5
#> 9 3 CAE 46.9
#> 10 4 OKC 47.0
#> # ℹ 26 more rows
On peut à tout moment “dégrouper” un tableau à l’aide de ungroup
. C’est nécessaire, dans l’exemple précédent, si on veut seulement récupérer les trois retards les plus importants pour l’ensemble des couples mois / destination.
%>%
flights group_by(month, dest) %>%
summarise(retard_moyen = mean(dep_delay, na.rm = TRUE)) %>%
ungroup() %>%
slice_max(retard_moyen, n = 3)
#> `summarise()` has grouped output by 'month'. You can override using the
#> `.groups` argument.
#> # A tibble: 3 × 3
#> month dest retard_moyen
#> <int> <chr> <dbl>
#> 1 12 BZN 75
#> 2 7 TUL 72.6
#> 3 3 DSM 71.0
On peut aussi spécifier précisément le comportement de dégroupage de summarise
en lui fournissant un argument supplémentaire .groups
qui peut prendre notamment les valeurs suivantes :
"drop_last"
: dégroupe seulement de la dernière variable de groupage"drop"
: dégroupe totalement le tableau résultat (équivaut à l’application d’unungroup
)"keep"
: conserve toutes les variables de groupage
Ce concept de dégroupage successif peut être un peu déroutant de prime abord. Il est donc utile de faire attention aux avertissements affichés par ces opérations, et il ne faut pas hésiter à ajouter un ungroup
en fin de pipeline si on sait qu’on ne souhaite pas utiliser les groupes encore existants par la suite.
À noter que la fonction count
, de son côté, renvoie un tableau non groupé.
%>%
flights count(month, dest)
#> # A tibble: 1,113 × 3
#> month dest n
#> <int> <chr> <int>
#> 1 1 ALB 64
#> 2 1 ATL 1396
#> 3 1 AUS 169
#> 4 1 AVL 2
#> 5 1 BDL 37
#> 6 1 BHM 25
#> 7 1 BNA 399
#> 8 1 BOS 1245
#> 9 1 BQN 93
#> 10 1 BTV 223
#> # ℹ 1,103 more rows
10.5 Autres fonctions utiles
dplyr
contient beaucoup d’autres fonctions utiles pour la manipulation de données.
10.5.1 slice_sample
Ce verbe permet de sélectionner aléatoirement un nombre de lignes (avec l’argument n
) ou une fraction des lignes (avec l’argument prop
) d’un tableau.
Ainsi si on veut choisir 5 lignes au hasard dans le tableau airports
:
%>% slice_sample(n = 5)
airports #> # A tibble: 5 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 JES Jesup-Wayne County Airport 31.6 -81.9 107 -5 A Amer…
#> 2 GLV Golovin Airport 64.6 -163. 59 -9 A Amer…
#> 3 ONT Ontario Intl 34.1 -118. 944 -8 A Amer…
#> 4 9A5 Barwick Lafayette Airport 34.7 -85.3 777 -5 A Amer…
#> 5 EKN Elkins Randolph Co Jennings Randol… 38.9 -79.9 1987 -5 A Amer…
Si on veut tirer au hasard 10% des lignes de flights
:
%>% slice_sample(prop = 0.1)
flights #> # A tibble: 33,677 × 22
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 4 7 1732 1729 3 2031 2024
#> 2 2013 3 13 1600 1605 -5 1917 1939
#> 3 2013 10 24 2022 1932 50 2254 2143
#> 4 2013 8 23 2058 2051 7 11 2358
#> 5 2013 3 13 1524 1530 -6 1837 1835
#> 6 2013 11 13 1856 1900 -4 2021 2014
#> 7 2013 7 28 757 800 -3 1051 1053
#> 8 2013 2 28 1510 1510 0 1747 1745
#> 9 2013 6 20 836 840 -4 1138 1139
#> 10 2013 4 12 1259 1300 -1 1416 1425
#> # ℹ 33,667 more rows
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
Ces fonctions sont utiles notamment pour faire de “l’échantillonnage” en tirant au hasard un certain nombre d’observations du tableau.
10.5.2 lead
et lag
lead
et lag
permettent de décaler les observations d’une variable d’un cran vers l’arrière (pour lead
) ou vers l’avant (pour lag
).
lead(1:5)
#> [1] 2 3 4 5 NA
lag(1:5)
#> [1] NA 1 2 3 4
Ceci peut être utile pour des données de type “séries temporelles”. Par exemple, on peut facilement calculer l’écart entre le retard au départ de chaque vol et celui du vol précédent :
%>%
flights mutate(
dep_delay_prev = lag(dep_delay),
dep_delay_diff = dep_delay - dep_delay_prev
%>%
) select(dep_delay_prev, dep_delay, dep_delay_diff)
#> # A tibble: 336,776 × 3
#> dep_delay_prev dep_delay dep_delay_diff
#> <dbl> <dbl> <dbl>
#> 1 NA 2 NA
#> 2 2 4 2
#> 3 4 2 -2
#> 4 2 -1 -3
#> 5 -1 -6 -5
#> 6 -6 -4 2
#> 7 -4 -5 -1
#> 8 -5 -3 2
#> 9 -3 -3 0
#> 10 -3 -2 1
#> # ℹ 336,766 more rows
10.5.3 distinct
et n_distinct
distinct
filtre les lignes du tableau pour ne conserver que les lignes distinctes, en supprimant toutes les lignes en double.
%>%
flights select(day, month) %>%
distinct()
#> # A tibble: 365 × 2
#> day month
#> <int> <int>
#> 1 1 1
#> 2 2 1
#> 3 3 1
#> 4 4 1
#> 5 5 1
#> 6 6 1
#> 7 7 1
#> 8 8 1
#> 9 9 1
#> 10 10 1
#> # ℹ 355 more rows
On peut lui spécifier une liste de variables : dans ce cas, pour toutes les observations ayant des valeurs identiques pour les variables en question, distinct
ne conservera que la première d’entre elles.
%>%
flights distinct(month, day)
#> # A tibble: 365 × 2
#> month day
#> <int> <int>
#> 1 1 1
#> 2 1 2
#> 3 1 3
#> 4 1 4
#> 5 1 5
#> 6 1 6
#> 7 1 7
#> 8 1 8
#> 9 1 9
#> 10 1 10
#> # ℹ 355 more rows
L’option .keep_all
permet, dans l’opération précédente, de conserver l’ensemble des colonnes du tableau :
%>%
flights distinct(month, day, .keep_all = TRUE)
#> # A tibble: 365 × 22
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 2 42 2359 43 518 442
#> 3 2013 1 3 32 2359 33 504 442
#> 4 2013 1 4 25 2359 26 505 442
#> 5 2013 1 5 14 2359 15 503 445
#> 6 2013 1 6 16 2359 17 451 442
#> 7 2013 1 7 49 2359 50 531 444
#> 8 2013 1 8 454 500 -6 625 648
#> 9 2013 1 9 2 2359 3 432 444
#> 10 2013 1 10 3 2359 4 426 437
#> # ℹ 355 more rows
#> # ℹ 14 more variables: 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>, duree_h <dbl>,
#> # distance_km <dbl>, vitesse <dbl>
La fonction n_distinct
, elle, renvoie le nombre de valeurs distinctes d’un vecteur. On peut notamment l’utiliser dans un summarise
.
Dans l’exemple qui suit on calcule, pour les trois aéroports de départ de la table flights
le nombre de valeurs distinctes de l’aéroport d’arrivée :
%>%
flights group_by(origin) %>%
summarise(n_dest = n_distinct(dest))
#> # A tibble: 3 × 2
#> origin n_dest
#> <chr> <int>
#> 1 EWR 86
#> 2 JFK 70
#> 3 LGA 68
10.5.4 relocate
relocate
peut être utilisé pour réordonner les colonnes d’une table. Par défaut, si on lui passe un ou plusieurs noms de colonnes, relocate
les place en début de tableau.
%>% relocate(lat, lon)
airports #> # A tibble: 1,458 × 8
#> lat lon faa name alt tz dst tzone
#> <dbl> <dbl> <chr> <chr> <dbl> <dbl> <chr> <chr>
#> 1 41.1 -80.6 04G Lansdowne Airport 1044 -5 A America/…
#> 2 32.5 -85.7 06A Moton Field Municipal Airport 264 -6 A America/…
#> 3 42.0 -88.1 06C Schaumburg Regional 801 -6 A America/…
#> 4 41.4 -74.4 06N Randall Airport 523 -5 A America/…
#> 5 31.1 -81.4 09J Jekyll Island Airport 11 -5 A America/…
#> 6 36.4 -82.2 0A9 Elizabethton Municipal Airport 1593 -5 A America/…
#> 7 41.5 -84.5 0G6 Williams County Airport 730 -5 A America/…
#> 8 42.9 -76.8 0G7 Finger Lakes Regional Airport 492 -5 A America/…
#> 9 39.8 -76.6 0P2 Shoestring Aviation Airfield 1000 -5 U America/…
#> 10 48.1 -123. 0S9 Jefferson County Intl 108 -8 A America/…
#> # ℹ 1,448 more rows
Les arguments supplémentaires .before
et .after
permettent de préciser à quel endroit déplacer la ou les colonnes indiquées.
%>% relocate(starts_with('tz'), .after = name)
airports #> # A tibble: 1,458 × 8
#> faa name tz tzone lat lon alt dst
#> <chr> <chr> <dbl> <chr> <dbl> <dbl> <dbl> <chr>
#> 1 04G Lansdowne Airport -5 America/… 41.1 -80.6 1044 A
#> 2 06A Moton Field Municipal Airport -6 America/… 32.5 -85.7 264 A
#> 3 06C Schaumburg Regional -6 America/… 42.0 -88.1 801 A
#> 4 06N Randall Airport -5 America/… 41.4 -74.4 523 A
#> 5 09J Jekyll Island Airport -5 America/… 31.1 -81.4 11 A
#> 6 0A9 Elizabethton Municipal Airport -5 America/… 36.4 -82.2 1593 A
#> 7 0G6 Williams County Airport -5 America/… 41.5 -84.5 730 A
#> 8 0G7 Finger Lakes Regional Airport -5 America/… 42.9 -76.8 492 A
#> 9 0P2 Shoestring Aviation Airfield -5 America/… 39.8 -76.6 1000 U
#> 10 0S9 Jefferson County Intl -8 America/… 48.1 -123. 108 A
#> # ℹ 1,448 more rows
10.6 Tables multiples
Le jeu de données nycflights13
est un exemple de données réparties en plusieurs tables. Ici on en a trois : les informations sur les vols dans flights
, celles sur les aéroports dans airports
et celles sur les compagnies aériennes dans airlines
.
dplyr
propose différentes fonctions permettant de travailler avec des données structurées de cette manière.
10.6.1 Concaténation : bind_rows
et bind_cols
Les fonctions bind_rows
et bind_cols
permettent d’ajouter des lignes (respectivement des colonnes) à une table à partir d’une ou plusieurs autres tables.
L’exemple suivant (certes très artificiel) montre l’utilisation de bind_rows
. On commence par créer trois tableaux t1
, t2
et t3
:
<- airports %>%
t1 select(faa, name, lat, lon) %>%
slice(1:2)
t1#> # A tibble: 2 × 4
#> faa name lat lon
#> <chr> <chr> <dbl> <dbl>
#> 1 04G Lansdowne Airport 41.1 -80.6
#> 2 06A Moton Field Municipal Airport 32.5 -85.7
<- airports %>%
t2 select(faa, name, lat, lon) %>%
slice(5:6)
t2#> # A tibble: 2 × 4
#> faa name lat lon
#> <chr> <chr> <dbl> <dbl>
#> 1 09J Jekyll Island Airport 31.1 -81.4
#> 2 0A9 Elizabethton Municipal Airport 36.4 -82.2
<- airports %>%
t3 select(faa, name) %>%
slice(100:101)
t3#> # A tibble: 2 × 2
#> faa name
#> <chr> <chr>
#> 1 ADW Andrews Afb
#> 2 AET Allakaket Airport
On concaténe ensuite les trois tables avec bind_rows
:
bind_rows(t1, t2, t3)
#> # A tibble: 6 × 4
#> faa name lat lon
#> <chr> <chr> <dbl> <dbl>
#> 1 04G Lansdowne Airport 41.1 -80.6
#> 2 06A Moton Field Municipal Airport 32.5 -85.7
#> 3 09J Jekyll Island Airport 31.1 -81.4
#> 4 0A9 Elizabethton Municipal Airport 36.4 -82.2
#> 5 ADW Andrews Afb NA NA
#> 6 AET Allakaket Airport NA NA
On remarquera que si des colonnes sont manquantes pour certaines tables, comme les colonnes lat
et lon
de t3
, des NA
sont automatiquement insérées.
Il peut être utile, quand on concatène des lignes, de garder une trace du tableau d’origine de chacune des lignes dans le tableau final. C’est possible grâce à l’argument .id
de bind_rows
. On passe à cet argument le nom d’une colonne qui contiendra l’indicateur d’origine des lignes :
bind_rows(t1, t2, t3, .id = "source")
#> # A tibble: 6 × 5
#> source faa name lat lon
#> <chr> <chr> <chr> <dbl> <dbl>
#> 1 1 04G Lansdowne Airport 41.1 -80.6
#> 2 1 06A Moton Field Municipal Airport 32.5 -85.7
#> 3 2 09J Jekyll Island Airport 31.1 -81.4
#> 4 2 0A9 Elizabethton Municipal Airport 36.4 -82.2
#> 5 3 ADW Andrews Afb NA NA
#> 6 3 AET Allakaket Airport NA NA
Par défaut la colonne .id
ne contient qu’un nombre, différent pour chaque tableau. On peut lui spécifier des valeurs plus explicites en “nommant” les tables dans bind_rows
de la manière suivante :
bind_rows(table1 = t1, table2 = t2, table3 = t3, .id = "source")
#> # A tibble: 6 × 5
#> source faa name lat lon
#> <chr> <chr> <chr> <dbl> <dbl>
#> 1 table1 04G Lansdowne Airport 41.1 -80.6
#> 2 table1 06A Moton Field Municipal Airport 32.5 -85.7
#> 3 table2 09J Jekyll Island Airport 31.1 -81.4
#> 4 table2 0A9 Elizabethton Municipal Airport 36.4 -82.2
#> 5 table3 ADW Andrews Afb NA NA
#> 6 table3 AET Allakaket Airport NA NA
bind_cols
permet de concaténer des colonnes et fonctionne de manière similaire :
<- flights %>% slice(1:5) %>% select(dep_delay, dep_time)
t1 <- flights %>% slice(1:5) %>% select(origin, dest)
t2 <- flights %>% slice(1:5) %>% select(arr_delay, arr_time)
t3 bind_cols(t1, t2, t3)
#> # A tibble: 5 × 6
#> dep_delay dep_time origin dest arr_delay arr_time
#> <dbl> <int> <chr> <chr> <dbl> <int>
#> 1 2 517 EWR IAH 11 830
#> 2 4 533 LGA IAH 20 850
#> 3 2 542 JFK MIA 33 923
#> 4 -1 544 JFK BQN -18 1004
#> 5 -6 554 LGA ATL -25 812
À noter que bind_cols
associe les lignes uniquement par position. Les lignes des différents tableaux associés doivent donc correspondre (et leur nombre doit être identique). Pour associer des tables par valeur, on doit utiliser des jointures.
10.6.2 Jointures
10.6.2.1 Clés implicites
Très souvent, les données relatives à une analyse sont réparties dans plusieurs tables différentes. Dans notre exemple, on peut voir que la table flights
contient le code de la compagnie aérienne du vol dans la variable carrier
:
%>% select(carrier)
flights #> # A tibble: 336,776 × 1
#> carrier
#> <chr>
#> 1 UA
#> 2 UA
#> 3 AA
#> 4 B6
#> 5 DL
#> 6 UA
#> 7 B6
#> 8 EV
#> 9 B6
#> 10 AA
#> # ℹ 336,766 more rows
Et que par ailleurs la table airlines
contient une information supplémentaire relative à ces compagnies, à savoir le nom complet.
airlines#> # A tibble: 16 × 2
#> carrier name
#> <chr> <chr>
#> 1 9E Endeavor Air Inc.
#> 2 AA American Airlines Inc.
#> 3 AS Alaska Airlines Inc.
#> 4 B6 JetBlue Airways
#> 5 DL Delta Air Lines Inc.
#> 6 EV ExpressJet Airlines Inc.
#> 7 F9 Frontier Airlines Inc.
#> 8 FL AirTran Airways Corporation
#> 9 HA Hawaiian Airlines Inc.
#> 10 MQ Envoy Air
#> 11 OO SkyWest Airlines Inc.
#> 12 UA United Air Lines Inc.
#> 13 US US Airways Inc.
#> 14 VX Virgin America
#> 15 WN Southwest Airlines Co.
#> 16 YV Mesa Airlines Inc.
Il est donc naturel de vouloir associer les deux, ici pour ajouter les noms complets des compagnies à la table flights
. Pour cela on va effectuer une jointure : les lignes d’une table seront associées à une autre en se basant non pas sur leur position, mais sur les valeurs d’une ou plusieurs colonnes. Ces colonnes sont appelées des clés.
Pour faire une jointure de ce type, on va utiliser la fonction left_join
:
left_join(flights, airlines)
Pour faciliter la lecture, on va afficher seulement certaines colonnes du résultat :
left_join(flights, airlines) %>%
select(month, day, carrier, name)
#> Joining with `by = join_by(carrier)`
#> # A tibble: 336,776 × 4
#> month day carrier name
#> <int> <int> <chr> <chr>
#> 1 1 1 UA United Air Lines Inc.
#> 2 1 1 UA United Air Lines Inc.
#> 3 1 1 AA American Airlines Inc.
#> 4 1 1 B6 JetBlue Airways
#> 5 1 1 DL Delta Air Lines Inc.
#> 6 1 1 UA United Air Lines Inc.
#> 7 1 1 B6 JetBlue Airways
#> 8 1 1 EV ExpressJet Airlines Inc.
#> 9 1 1 B6 JetBlue Airways
#> 10 1 1 AA American Airlines Inc.
#> # ℹ 336,766 more rows
On voit que la table résultat est bien la fusion des deux tables d’origine selon les valeurs des deux colonnes clés carrier
. On est parti de la table flights
, et pour chaque ligne de celle-ci on a ajouté les colonnes de airlines
pour lesquelles la valeur de carrier
est la même. On a donc bien une nouvelle colonne name
dans notre table résultat, avec le nom complet de la compagnie aérienne.
À noter qu’on peut tout à fait utiliser le pipe avec les fonctions de jointure :
flights %>% left_join(airlines)
.
Nous sommes ici dans le cas le plus simple concernant les clés de jointure : les deux clés sont uniques et portent le même nom dans les deux tables. Par défaut, si on ne lui spécifie pas explicitement les clés, dplyr
fusionne en utilisant l’ensemble des colonnes communes aux deux tables. On peut d’ailleurs voir dans cet exemple qu’un message a été affiché précisant que la jointure s’est bien faite sur la variable carrier
.
10.6.2.2 Clés explicites
La table airports
, contient des informations supplémentaires sur les aéroports : nom complet, altitude, position géographique, etc. Chaque aéroport est identifié par un code contenu dans la colonne faa
.
Si on regarde la table flights
, on voit que le code d’identification des aéroports apparaît à deux endroits différents : pour l’aéroport de départ dans la colonne origin
, et pour celui d’arrivée dans la colonne dest
. On a donc deux clés de jointure possibles, et qui portent un nom différent de la clé de airports
.
On va commencer par fusionner les données concernant l’aéroport de départ. Pour simplifier l’affichage des résultats, on va se contenter d’un sous-ensemble des deux tables :
<- flights %>% select(month, day, origin, dest)
flights_ex <- airports %>% select(faa, alt, name) airports_ex
Si on se contente d’un left_join
comme à l’étape précédente, on obtient un message d’erreur car aucune colonne commune ne peut être identifiée comme clé de jointure :
%>% left_join(airports_ex)
flights_ex #> Error in `left_join()`:
#> ! `by` must be supplied when `x` and `y` have no common variables.
#> ℹ Use `cross_join()` to perform a cross-join.
On doit donc spécifier explicitement les clés avec l’argument by
de left_join
. Ici la clé est nommée origin
dans la première table, et faa
dans la seconde. La syntaxe est donc la suivante :
%>%
flights_ex left_join(airports_ex, by = c("origin" = "faa"))
#> # A tibble: 336,776 × 6
#> month day origin dest alt name
#> <int> <int> <chr> <chr> <dbl> <chr>
#> 1 1 1 EWR IAH 18 Newark Liberty Intl
#> 2 1 1 LGA IAH 22 La Guardia
#> 3 1 1 JFK MIA 13 John F Kennedy Intl
#> 4 1 1 JFK BQN 13 John F Kennedy Intl
#> 5 1 1 LGA ATL 22 La Guardia
#> 6 1 1 EWR ORD 18 Newark Liberty Intl
#> 7 1 1 EWR FLL 18 Newark Liberty Intl
#> 8 1 1 LGA IAD 22 La Guardia
#> 9 1 1 JFK MCO 13 John F Kennedy Intl
#> 10 1 1 LGA ORD 22 La Guardia
#> # ℹ 336,766 more rows
On constate que les deux nouvelles colonnes name
et alt
contiennent bien les données correspondant à l’aéroport de départ.
On va stocker le résultat de cette jointure dans la table flights_ex
:
<- flights_ex %>%
flights_ex left_join(airports_ex, by = c("origin" = "faa"))
Supposons qu’on souhaite maintenant fusionner à nouveau les informations de la table airports
, mais cette fois pour les aéroports d’arrivée de notre nouvelle table flights_ex
. Les deux clés sont donc désormais dest
dans la première table, et faa
dans la deuxième. La syntaxe est donc la suivante :
%>%
flights_ex left_join(airports_ex, by = c("dest" = "faa"))
#> # A tibble: 336,776 × 8
#> month day origin dest alt.x name.x alt.y name.y
#> <int> <int> <chr> <chr> <dbl> <chr> <dbl> <chr>
#> 1 1 1 EWR IAH 18 Newark Liberty Intl 97 George Bush Interco…
#> 2 1 1 LGA IAH 22 La Guardia 97 George Bush Interco…
#> 3 1 1 JFK MIA 13 John F Kennedy Intl 8 Miami Intl
#> 4 1 1 JFK BQN 13 John F Kennedy Intl NA <NA>
#> 5 1 1 LGA ATL 22 La Guardia 1026 Hartsfield Jackson …
#> 6 1 1 EWR ORD 18 Newark Liberty Intl 668 Chicago Ohare Intl
#> 7 1 1 EWR FLL 18 Newark Liberty Intl 9 Fort Lauderdale Hol…
#> 8 1 1 LGA IAD 22 La Guardia 313 Washington Dulles I…
#> 9 1 1 JFK MCO 13 John F Kennedy Intl 96 Orlando Intl
#> 10 1 1 LGA ORD 22 La Guardia 668 Chicago Ohare Intl
#> # ℹ 336,766 more rows
Cela fonctionne, les informations de l’aéroport d’arrivée ont bien été ajoutées, mais on constate que les colonnes ont été renommées. En effet, ici les deux tables fusionnées contenaient toutes les deux des colonnes name
et alt
. Comme on ne peut pas avoir deux colonnes avec le même nom dans un tableau, dplyr
a renommé les colonnes de la première table en name.x
et alt.x
, et celles de la deuxième en name.y
et alt.y
.
C’est pratique, mais pas forcément très parlant. On pourrait renommer manuellement les colonnes avec rename
avant de faire la jointure pour avoir des intitulés plus explicites, mais on peut aussi utiliser l’argument suffix
de left_join
, qui permet d’indiquer les suffixes à ajouter aux colonnes.
%>%
flights_ex left_join(
airports_ex,by = c("dest" = "faa"),
suffix = c("_depart", "_arrivee")
)#> # A tibble: 336,776 × 8
#> month day origin dest alt_depart name_depart alt_arrivee name_arrivee
#> <int> <int> <chr> <chr> <dbl> <chr> <dbl> <chr>
#> 1 1 1 EWR IAH 18 Newark Liberty … 97 George Bush…
#> 2 1 1 LGA IAH 22 La Guardia 97 George Bush…
#> 3 1 1 JFK MIA 13 John F Kennedy … 8 Miami Intl
#> 4 1 1 JFK BQN 13 John F Kennedy … NA <NA>
#> 5 1 1 LGA ATL 22 La Guardia 1026 Hartsfield …
#> 6 1 1 EWR ORD 18 Newark Liberty … 668 Chicago Oha…
#> 7 1 1 EWR FLL 18 Newark Liberty … 9 Fort Lauder…
#> 8 1 1 LGA IAD 22 La Guardia 313 Washington …
#> 9 1 1 JFK MCO 13 John F Kennedy … 96 Orlando Intl
#> 10 1 1 LGA ORD 22 La Guardia 668 Chicago Oha…
#> # ℹ 336,766 more rows
On obtient ainsi directement des noms de colonnes nettement plus clairs.
10.6.3 Types de jointures
Jusqu’à présent nous avons utilisé la fonction left_join
, mais il existe plusieurs types de jointures.
Partons de deux tables d’exemple, personnes
et voitures
:
<- tibble(
personnes nom = c("Sylvie", "Sylvie", "Monique", "Gunter", "Rayan", "Rayan"),
voiture = c("Twingo", "Ferrari", "Scenic", "Lada", "Twingo", "Clio")
)
nom | voiture |
---|---|
Sylvie | Twingo |
Sylvie | Ferrari |
Monique | Scenic |
Gunter | Lada |
Rayan | Twingo |
Rayan | Clio |
<- tibble(
voitures voiture = c("Twingo", "Ferrari", "Clio", "Lada", "208"),
vitesse = c("140", "280", "160", "85", "160")
)
voiture | vitesse |
---|---|
Twingo | 140 |
Ferrari | 280 |
Clio | 160 |
Lada | 85 |
208 | 160 |
10.6.3.1 left_join
Si on fait un left_join
de voitures
sur personnes
:
%>% left_join(voitures) personnes
#> Joining with `by = join_by(voiture)`
nom | voiture | vitesse |
---|---|---|
Sylvie | Twingo | 140 |
Sylvie | Ferrari | 280 |
Monique | Scenic | NA |
Gunter | Lada | 85 |
Rayan | Twingo | 140 |
Rayan | Clio | 160 |
On voit que chaque ligne de personnes
est bien présente, et qu’on lui a ajouté une ligne de voitures
correspondante si elle existe. Dans le cas du Scenic
, il n’y a avait pas de ligne dans voitures
, donc vitesse
a été mise à NA
. Dans le cas de 208
, présente dans voitures
mais pas dans personnes
, la ligne n’apparaît pas.
Si on fait un left_join
cette fois de personnes
sur voitures
, c’est l’inverse :
%>% left_join(personnes) voitures
#> Joining with `by = join_by(voiture)`
voiture | vitesse | nom |
---|---|---|
Twingo | 140 | Sylvie |
Twingo | 140 | Rayan |
Ferrari | 280 | Sylvie |
Clio | 160 | Rayan |
Lada | 85 | Gunter |
208 | 160 | NA |
La ligne 208
est là, mais nom
est à NA
. Par contre Monique
est absente. Et on remarquera que la ligne Twingo
, présente deux fois dans personnes
, a été dupliquée pour être associée aux deux lignes de données de Sylvie
et Rayan
.
En résumé, quand on fait un left_join(x, y)
, toutes les lignes de x
sont présentes, et dupliquées si nécessaire quand elles apparaissent plusieurs fois dans y
. Les lignes de y
non présentes dans x
disparaissent. Les lignes de x
non présentes dans y
se voient attribuer des NA
pour les nouvelles colonnes.
Intuitivement, on pourrait considérer que left_join(x, y)
signifie “ramener l’information de la table y
sur la table x
”.
En général, left_join
sera le type de jointures le plus fréquemment utilisé.
10.6.3.2 right_join
La jointure right_join
est l’exacte symétrique de left_join
, c’est-à dire que right_join(x, y)
est équivalent à left_join(y, x)
:
%>% right_join(voitures) personnes
#> Joining with `by = join_by(voiture)`
nom | voiture | vitesse |
---|---|---|
Sylvie | Twingo | 140 |
Sylvie | Ferrari | 280 |
Gunter | Lada | 85 |
Rayan | Twingo | 140 |
Rayan | Clio | 160 |
NA | 208 | 160 |
10.6.3.3 inner_join
Dans le cas de inner_join(x, y)
, seules les lignes présentes à la fois dans x
et y
sont conservées (et si nécessaire dupliquées) dans la table résultat :
%>% inner_join(voitures) personnes
#> Joining with `by = join_by(voiture)`
nom | voiture | vitesse |
---|---|---|
Sylvie | Twingo | 140 |
Sylvie | Ferrari | 280 |
Gunter | Lada | 85 |
Rayan | Twingo | 140 |
Rayan | Clio | 160 |
Ici la ligne 208
est absente, ainsi que la ligne Monique
, qui dans le cas d’un left_join
avait été conservée et s’était vue attribuer une vitesse
à NA
.
10.6.3.4 full_join
Dans le cas de full_join(x, y)
, toutes les lignes de x
et toutes les lignes de y
sont conservées (avec des NA
ajoutés si nécessaire) même si elles sont absentes de l’autre table :
%>% full_join(voitures) personnes
#> Joining with `by = join_by(voiture)`
nom | voiture | vitesse |
---|---|---|
Sylvie | Twingo | 140 |
Sylvie | Ferrari | 280 |
Monique | Scenic | NA |
Gunter | Lada | 85 |
Rayan | Twingo | 140 |
Rayan | Clio | 160 |
NA | 208 | 160 |
10.6.3.5 semi_join et anti_join
semi_join
et anti_join
sont des jointures filtrantes, c’est-à-dire qu’elles sélectionnent les lignes de x
sans ajouter les colonnes de y
.
Ainsi, semi_join
ne conservera que les lignes de x
pour lesquelles une ligne de y
existe également, et supprimera les autres. Dans notre exemple, la ligne Monique
est donc supprimée :
%>% semi_join(voitures) personnes
#> Joining with `by = join_by(voiture)`
nom | voiture |
---|---|
Sylvie | Twingo |
Sylvie | Ferrari |
Gunter | Lada |
Rayan | Twingo |
Rayan | Clio |
Un anti_join
fait l’inverse, il ne conserve que les lignes de x
absentes de y
. Dans notre exemple, on ne garde donc que la ligne Monique
:
%>% anti_join(voitures) personnes
#> Joining with `by = join_by(voiture)`
nom | voiture |
---|---|
Monique | Scenic |
10.7 Ressources
Toutes les ressources ci-dessous sont en anglais…
Le livre R for data science, librement accessible en ligne, contient plusieurs chapitres très complets sur la manipulation des données, notamment :
- Data transformation pour les manipulations
- Relational data pour les tables multiples
Le site de l’extension comprend une liste des fonctions et les pages d’aide associées, mais aussi une introduction au package et plusieurs articles dont un spécifiquement sur les jointures.
Enfin, une “antisèche” très synthétique est également accessible depuis RStudio, en allant dans le menu Help puis Cheatsheets et Data Transformation with dplyr.
10.8 Exercices
On commence par charger les extensions et les données nécessaires.
library(tidyverse)
library(nycflights13)
data(flights)
data(airports)
data(airlines)
10.8.1 Les verbes de base de dplyr
Exercice 1.1
Sélectionner la dixième ligne du tableau des aéroports (airports
).
#> # A tibble: 1 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 0S9 Jefferson County Intl 48.1 -123. 108 -8 A America/Los_Angeles
slice(airports, 10)
Sélectionner les 5 premières lignes de la table airlines
.
#> # A tibble: 5 × 2
#> carrier name
#> <chr> <chr>
#> 1 9E Endeavor Air Inc.
#> 2 AA American Airlines Inc.
#> 3 AS Alaska Airlines Inc.
#> 4 B6 JetBlue Airways
#> 5 DL Delta Air Lines Inc.
slice_head(airlines, n = 5)
Sélectionner l’aéroport avec l’altitude la plus basse.
#> # A tibble: 1 × 8
#> faa name lat lon alt tz dst tzone
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 IPL Imperial Co 32.8 -116. -54 -8 A America/Los_Angeles
slice_min(airports, alt)
Exercice 1.2
Sélectionnez les vols du mois de juillet (variable month
).
#> # A tibble: 29,425 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 7 1 1 2029 212 236 2359
#> 2 2013 7 1 2 2359 3 344 344
#> 3 2013 7 1 29 2245 104 151 1
#> 4 2013 7 1 43 2130 193 322 14
#> 5 2013 7 1 44 2150 174 300 100
#> 6 2013 7 1 46 2051 235 304 2358
#> 7 2013 7 1 48 2001 287 308 2305
#> 8 2013 7 1 58 2155 183 335 43
#> 9 2013 7 1 100 2146 194 327 30
#> 10 2013 7 1 100 2245 135 337 135
#> # ℹ 29,415 more rows
#> # ℹ 11 more variables: 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 == 7)
Sélectionnez les vols avec un retard à l’arrivée (variable arr_delay
) compris entre 5 et 15 minutes.
#> # A tibble: 36,392 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 554 558 -4 740 728
#> 3 2013 1 1 558 600 -2 753 745
#> 4 2013 1 1 558 600 -2 924 917
#> 5 2013 1 1 600 600 0 837 825
#> 6 2013 1 1 611 600 11 945 931
#> 7 2013 1 1 623 610 13 920 915
#> 8 2013 1 1 624 630 -6 840 830
#> 9 2013 1 1 629 630 -1 824 810
#> 10 2013 1 1 632 608 24 740 728
#> # ℹ 36,382 more rows
#> # ℹ 11 more variables: 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, arr_delay >= 5 & arr_delay <= 15)
Sélectionnez les vols des compagnies Delta, United et American (codes DL
, UA
et AA
de la variable carrier
).
#> # A tibble: 139,504 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 554 600 -6 812 837
#> 5 2013 1 1 554 558 -4 740 728
#> 6 2013 1 1 558 600 -2 753 745
#> 7 2013 1 1 558 600 -2 924 917
#> 8 2013 1 1 558 600 -2 923 937
#> 9 2013 1 1 559 600 -1 941 910
#> 10 2013 1 1 559 600 -1 854 902
#> # ℹ 139,494 more rows
#> # ℹ 11 more variables: 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, carrier %in% c("DL", "UA", "AA"))
Exercice 1.3
Triez la table flights
par retard au départ décroissant.
#> # A tibble: 336,776 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 6 15 1432 1935 1137 1607 2120
#> 3 2013 1 10 1121 1635 1126 1239 1810
#> 4 2013 9 20 1139 1845 1014 1457 2210
#> 5 2013 7 22 845 1600 1005 1044 1815
#> 6 2013 4 10 1100 1900 960 1342 2211
#> 7 2013 3 17 2321 810 911 135 1020
#> 8 2013 6 27 959 1900 899 1236 2226
#> 9 2013 7 22 2257 759 898 121 1026
#> 10 2013 12 5 756 1700 896 1058 2020
#> # ℹ 336,766 more rows
#> # ℹ 11 more variables: 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>
arrange(flights, desc(dep_delay))
Exercice 1.4
Sélectionnez les colonnes name
, lat
et lon
de la table airports
#> # A tibble: 1,458 × 3
#> name lat lon
#> <chr> <dbl> <dbl>
#> 1 Lansdowne Airport 41.1 -80.6
#> 2 Moton Field Municipal Airport 32.5 -85.7
#> 3 Schaumburg Regional 42.0 -88.1
#> 4 Randall Airport 41.4 -74.4
#> 5 Jekyll Island Airport 31.1 -81.4
#> 6 Elizabethton Municipal Airport 36.4 -82.2
#> 7 Williams County Airport 41.5 -84.5
#> 8 Finger Lakes Regional Airport 42.9 -76.8
#> 9 Shoestring Aviation Airfield 39.8 -76.6
#> 10 Jefferson County Intl 48.1 -123.
#> # ℹ 1,448 more rows
select(airports, name, lat, lon)
Sélectionnez toutes les colonnes de la table airports
sauf les colonnes tz
et tzone
#> # A tibble: 1,458 × 6
#> faa name lat lon alt dst
#> <chr> <chr> <dbl> <dbl> <dbl> <chr>
#> 1 04G Lansdowne Airport 41.1 -80.6 1044 A
#> 2 06A Moton Field Municipal Airport 32.5 -85.7 264 A
#> 3 06C Schaumburg Regional 42.0 -88.1 801 A
#> 4 06N Randall Airport 41.4 -74.4 523 A
#> 5 09J Jekyll Island Airport 31.1 -81.4 11 A
#> 6 0A9 Elizabethton Municipal Airport 36.4 -82.2 1593 A
#> 7 0G6 Williams County Airport 41.5 -84.5 730 A
#> 8 0G7 Finger Lakes Regional Airport 42.9 -76.8 492 A
#> 9 0P2 Shoestring Aviation Airfield 39.8 -76.6 1000 U
#> 10 0S9 Jefferson County Intl 48.1 -123. 108 A
#> # ℹ 1,448 more rows
select(airports, -tz, -tzone)
Sélectionnez toutes les colonnes de la table flights
dont les noms se terminent par “delay”.
#> # A tibble: 336,776 × 2
#> dep_delay arr_delay
#> <dbl> <dbl>
#> 1 2 11
#> 2 4 20
#> 3 2 33
#> 4 -1 -18
#> 5 -6 -25
#> 6 -4 12
#> 7 -5 19
#> 8 -3 -14
#> 9 -3 -8
#> 10 -2 8
#> # ℹ 336,766 more rows
select(flights, ends_with("delay"))
Dans la table airports
, renommez la colonne alt
en altitude
et la colonne tzone
en fuseau_horaire
.
#> # A tibble: 1,458 × 8
#> faa name lat lon altitude tz dst fuseau_horaire
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A America/New_Y…
#> 2 06A Moton Field Municipal… 32.5 -85.7 264 -6 A America/Chica…
#> 3 06C Schaumburg Regional 42.0 -88.1 801 -6 A America/Chica…
#> 4 06N Randall Airport 41.4 -74.4 523 -5 A America/New_Y…
#> 5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A America/New_Y…
#> 6 0A9 Elizabethton Municipa… 36.4 -82.2 1593 -5 A America/New_Y…
#> 7 0G6 Williams County Airpo… 41.5 -84.5 730 -5 A America/New_Y…
#> 8 0G7 Finger Lakes Regional… 42.9 -76.8 492 -5 A America/New_Y…
#> 9 0P2 Shoestring Aviation A… 39.8 -76.6 1000 -5 U America/New_Y…
#> 10 0S9 Jefferson County Intl 48.1 -123. 108 -8 A America/Los_A…
#> # ℹ 1,448 more rows
rename(airports, altitude = alt, fuseau_horaire = tzone)
Exercice 1.5
Dans la table airports
, la colonne alt
contient l’altitude de l’aéroport en pieds. Créer une nouvelle variable alt_m
contenant l’altitude en mètres (on convertit des pieds en mètres en les divisant par 3.2808). Sélectionner dans la table obtenue uniquement les deux colonnes alt
et alt_m
.
#> # A tibble: 1,458 × 2
#> alt alt_m
#> <dbl> <dbl>
#> 1 1044 318.
#> 2 264 80.5
#> 3 801 244.
#> 4 523 159.
#> 5 11 3.35
#> 6 1593 486.
#> 7 730 223.
#> 8 492 150.
#> 9 1000 305.
#> 10 108 32.9
#> # ℹ 1,448 more rows
<- mutate(airports, alt_m = alt / 3.2808)
tmp select(tmp, alt, alt_m)
10.8.2 Enchaîner des opérations
Exercice 2.1
Réécrire le code de l’exercice précédent en utilisant le pipe %>%
.
%>%
airports mutate(alt_m = alt / 3.2808) %>%
select(alt, alt_m)
Exercice 2.2
En utilisant le pipe, sélectionnez les vols à destination de San Francico (code SFO
de la variable dest
) et triez-les selon le retard au départ décroissant (variable dep_delay
).
#> # A tibble: 13,331 × 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 9 20 1139 1845 1014 1457 2210
#> 2 2013 7 7 2123 1030 653 17 1345
#> 3 2013 7 7 2059 1030 629 106 1350
#> 4 2013 7 6 149 1600 589 456 1935
#> 5 2013 7 10 133 1800 453 455 2130
#> 6 2013 7 10 2342 1630 432 312 1959
#> 7 2013 7 7 2204 1525 399 107 1823
#> 8 2013 7 7 2306 1630 396 250 1959
#> 9 2013 6 23 1833 1200 393 NA 1507
#> 10 2013 7 10 2232 1609 383 138 1928
#> # ℹ 13,321 more rows
#> # ℹ 11 more variables: 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>
%>%
flights filter(dest == "SFO") %>%
arrange(desc(dep_delay))
Exercice 2.3
Sélectionnez les vols des mois de septembre et octobre, conservez les colonnes dest
et dep_delay
, créez une nouvelle variable retard_h
contenant le retard au départ en heures, et conservez uniquement les 5 lignes avec les plus grandes valeurs de retard_h
.
#> # A tibble: 5 × 3
#> dest dep_delay retard_h
#> <chr> <dbl> <dbl>
#> 1 SFO 1014 16.9
#> 2 ATL 702 11.7
#> 3 DTW 696 11.6
#> 4 ATL 602 10.0
#> 5 MSP 593 9.88
%>%
flights filter(month %in% c(9, 10)) %>%
select(dest, dep_delay) %>%
mutate(retard_h = dep_delay / 60) %>%
slice_max(retard_h, n = 5)
10.8.3 group_by
et summarise
Exercice 3.1
Affichez le nombre de vols par mois.
#> # A tibble: 12 × 2
#> month n
#> <int> <int>
#> 1 1 27004
#> 2 2 24951
#> 3 3 28834
#> 4 4 28330
#> 5 5 28796
#> 6 6 28243
#> 7 7 29425
#> 8 8 29327
#> 9 9 27574
#> 10 10 28889
#> 11 11 27268
#> 12 12 28135
%>%
flights count(month)
Triez la table résultat selon le nombre de vols croissant.
#> # A tibble: 12 × 2
#> month n
#> <int> <int>
#> 1 2 24951
#> 2 1 27004
#> 3 11 27268
#> 4 9 27574
#> 5 12 28135
#> 6 6 28243
#> 7 4 28330
#> 8 5 28796
#> 9 3 28834
#> 10 10 28889
#> 11 8 29327
#> 12 7 29425
%>%
flights count(month) %>%
arrange(n)
Exercice 3.2
Calculer la distance moyenne des vols selon l’aéroport de départ (variable origin
).
#> # A tibble: 3 × 2
#> origin distance_moyenne
#> <chr> <dbl>
#> 1 EWR 1057.
#> 2 JFK 1266.
#> 3 LGA 780.
%>%
flights group_by(origin) %>%
summarise(distance_moyenne = mean(distance))
Exercice 3.3
Calculer le nombre de vols à destination de Los Angeles (code LAX
) pour chaque mois de l’année.
#> # A tibble: 12 × 2
#> month n
#> <int> <int>
#> 1 1 1159
#> 2 2 1030
#> 3 3 1178
#> 4 4 1382
#> 5 5 1453
#> 6 6 1430
#> 7 7 1500
#> 8 8 1505
#> 9 9 1384
#> 10 10 1409
#> 11 11 1336
#> 12 12 1408
%>%
flights filter(dest == "LAX") %>%
count(month)
Exercice 3.4
Calculer le nombre de vols selon le mois et la destination.
#> # A tibble: 1,113 × 3
#> month dest n
#> <int> <chr> <int>
#> 1 1 ALB 64
#> 2 1 ATL 1396
#> 3 1 AUS 169
#> 4 1 AVL 2
#> 5 1 BDL 37
#> 6 1 BHM 25
#> 7 1 BNA 399
#> 8 1 BOS 1245
#> 9 1 BQN 93
#> 10 1 BTV 223
#> # ℹ 1,103 more rows
%>%
flights count(month, dest)
Ne conserver, pour chaque mois, que la destination avec le nombre maximal de vols.
#> # A tibble: 12 × 3
#> # Groups: month [12]
#> month dest n
#> <int> <chr> <int>
#> 1 1 ATL 1396
#> 2 2 ATL 1267
#> 3 3 ATL 1448
#> 4 4 ATL 1490
#> 5 5 ORD 1582
#> 6 6 ORD 1547
#> 7 7 ORD 1573
#> 8 8 ORD 1604
#> 9 9 ORD 1582
#> 10 10 ORD 1604
#> 11 11 ATL 1384
#> 12 12 ATL 1463
%>%
flights count(month, dest) %>%
group_by(month) %>%
slice_max(n)
Exercice 3.5
Calculer le nombre de vols selon le mois. Ajouter une colonne comportant le pourcentage de vols annuels réalisés par mois.
#> # A tibble: 12 × 3
#> month n pourcentage
#> <int> <int> <dbl>
#> 1 1 27004 8.02
#> 2 2 24951 7.41
#> 3 3 28834 8.56
#> 4 4 28330 8.41
#> 5 5 28796 8.55
#> 6 6 28243 8.39
#> 7 7 29425 8.74
#> 8 8 29327 8.71
#> 9 9 27574 8.19
#> 10 10 28889 8.58
#> 11 11 27268 8.10
#> 12 12 28135 8.35
%>%
flights count(month) %>%
mutate(pourcentage = n / sum(n) * 100)
Exercice 3.6
Calculer, pour chaque aéroport de départ et de destination, la durée moyenne des vols (variable air_time). Pour chaque aéroport de départ, ne conserver que la destination avec la durée moyenne la plus longue.
#> `summarise()` has grouped output by 'origin'. You can override using the
#> `.groups` argument.
#> # A tibble: 3 × 3
#> # Groups: origin [3]
#> origin dest duree_moyenne
#> <chr> <chr> <dbl>
#> 1 EWR HNL 612.
#> 2 JFK HNL 623.
#> 3 LGA DEN 228.
%>%
flights group_by(origin, dest) %>%
summarise(duree_moyenne = mean(air_time, na.rm = TRUE)) %>%
# Le group_by suivant n'est pas obligatoire
group_by(origin) %>%
slice_max(duree_moyenne)
10.8.4 Jointures
Exercice 4.1
Faire la jointure de la table airlines
sur la table flights
à l’aide de left_join
.
#> # A tibble: 336,776 × 20
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> 7 2013 1 1 555 600 -5 913 854
#> 8 2013 1 1 557 600 -3 709 723
#> 9 2013 1 1 557 600 -3 838 846
#> 10 2013 1 1 558 600 -2 753 745
#> # ℹ 336,766 more rows
#> # ℹ 12 more variables: 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>, name <chr>
%>%
flights left_join(airlines)
Exercice 4.2
À partir de la table résultat de l’exercice précédent, calculer le retard moyen au départ pour chaque compagnie, et trier selon ce retard décroissant.
#> # A tibble: 16 × 2
#> name retard_moyen
#> <chr> <dbl>
#> 1 Frontier Airlines Inc. 20.2
#> 2 ExpressJet Airlines Inc. 20.0
#> 3 Mesa Airlines Inc. 19.0
#> 4 AirTran Airways Corporation 18.7
#> 5 Southwest Airlines Co. 17.7
#> 6 Endeavor Air Inc. 16.7
#> 7 JetBlue Airways 13.0
#> 8 Virgin America 12.9
#> 9 SkyWest Airlines Inc. 12.6
#> 10 United Air Lines Inc. 12.1
#> 11 Envoy Air 10.6
#> 12 Delta Air Lines Inc. 9.26
#> 13 American Airlines Inc. 8.59
#> 14 Alaska Airlines Inc. 5.80
#> 15 Hawaiian Airlines Inc. 4.90
#> 16 US Airways Inc. 3.78
%>%
flights left_join(airlines) %>%
group_by(name) %>%
summarise(retard_moyen = mean(dep_delay, na.rm = TRUE)) %>%
arrange(desc(retard_moyen))
Exercice 4.3
Faire la jointure de la table airports
sur la table flights
en utilisant comme clé le code de l’aéroport de destination.
#> # A tibble: 336,776 × 26
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> 7 2013 1 1 555 600 -5 913 854
#> 8 2013 1 1 557 600 -3 709 723
#> 9 2013 1 1 557 600 -3 838 846
#> 10 2013 1 1 558 600 -2 753 745
#> # ℹ 336,766 more rows
#> # ℹ 18 more variables: 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>, name <chr>, lat <dbl>,
#> # lon <dbl>, alt <dbl>, tz <dbl>, dst <chr>, tzone <chr>
%>%
flights left_join(airports, by = c("dest" = "faa"))
À partir de cette table, afficher pour chaque mois le nom de l’aéroport de destination ayant eu le plus petit nombre de vol.
#> # A tibble: 14 × 3
#> # Groups: month [12]
#> month name n
#> <int> <chr> <int>
#> 1 1 Key West Intl 1
#> 2 2 Jackson Hole Airport 3
#> 3 3 Bangor Intl 2
#> 4 4 Key West Intl 1
#> 5 4 Myrtle Beach Intl 1
#> 6 5 Columbia Metropolitan 9
#> 7 6 Myrtle Beach Intl 1
#> 8 7 La Guardia 1
#> 9 8 South Bend Rgnl 1
#> 10 9 South Bend Rgnl 5
#> 11 10 Albany Intl 1
#> 12 10 South Bend Rgnl 1
#> 13 11 Blue Grass 1
#> 14 12 South Bend Rgnl 1
%>%
flights left_join(airports, by = c("dest" = "faa")) %>%
count(month, name) %>%
group_by(month) %>%
slice_min(n)
Exercice 4.4
Créer une table indiquant, pour chaque vol, uniquement le nom de l’aéroport de départ et celui de l’aéroport d’arrivée.
#> # A tibble: 336,776 × 2
#> orig_name dest_name
#> <chr> <chr>
#> 1 Newark Liberty Intl George Bush Intercontinental
#> 2 La Guardia George Bush Intercontinental
#> 3 John F Kennedy Intl Miami Intl
#> 4 John F Kennedy Intl <NA>
#> 5 La Guardia Hartsfield Jackson Atlanta Intl
#> 6 Newark Liberty Intl Chicago Ohare Intl
#> 7 Newark Liberty Intl Fort Lauderdale Hollywood Intl
#> 8 La Guardia Washington Dulles Intl
#> 9 John F Kennedy Intl Orlando Intl
#> 10 La Guardia Chicago Ohare Intl
#> # ℹ 336,766 more rows
%>%
flights left_join(airports, by = c("dest" = "faa")) %>%
rename(dest_name = name) %>%
left_join(airports, by = c("origin" = "faa")) %>%
rename(orig_name = name) %>%
select(orig_name, dest_name)
10.8.5 Bonus
Exercice 5.1
Calculer le nombre de vols selon l’aéroport de destination, et fusionnez la table airports
sur le résultat avec left_join
. Stocker le résultat final dans un objet nommé flights_dest
.
<- flights %>%
flights_dest count(dest) %>%
left_join(airports, by = c("dest"="faa"))
Créez une carte interactive des résultats avec le package leaflet
et le code suivant :
library(leaflet)
leaflet(data = flights_dest) %>%
%>%
addTiles addCircles(lng = ~lon, lat = ~lat, radius = ~n * 10, popup = ~name)
#> Warning in validateCoords(lng, lat, funcName): Data contains 4 rows with either
#> missing or invalid lat/lon values and will be ignored
À noter que cette opération est un peu plus “fragile” que les autres, car si l’ordre des colonnes change elle peut renvoyer un résultat différent.↩︎
Il est également possible de renommer des colonnes directement avec
select
, avec la même syntaxe que pourrename
.↩︎Le pipe a été introduit à l’origine par l’extension
magrittr
, et repris pardplyr
↩︎