8  dplyr

dplyr est l’un des packages les plus connus du tidyverse. Il facilite le traitement et la manipulation des tableaux de données (qu’il s’agisse de data frame ou de tibble). Il propose une syntaxe claire et cohérente, sous formes de verbes correspondant à des fonctions.

dplyr part du principe que les données sont tidy (chaque variable est une colonne, chaque observation est une ligne, voir Chapitre 5). Les verbes de dplyr prennent en entrée un tableau de données1 (data frame ou tibble) et renvoient systématiquement un tibble.

  • 1 Le package dbplyr permets d’étendre les verbes de dplyr à des tables de bases de données SQL, dtplyr à des tableaux de données du type data.table et srvyr à des données pondérées du type survey.

  • 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ée). 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 :

    On va charger les trois tables du jeu de données :

    library(nycflights13)
    ## Chargement des trois tables du jeu de données
    data(flights)
    data(airports)
    data(airlines)

    Normalement trois objets correspondant aux trois tables ont dû apparaître dans votre environnement.

    8.1 Opérations sur les lignes

    8.1.1 filter()

    dplyr::filter() sélectionne des lignes d’un tableau de données selon une condition. On lui passe en paramètre un test, et seules les lignes pour lesquelles ce test renvoi TRUE (vrai) sont conservées2.

  • 2 Si le test renvoie faux (FALSE) ou une valeur manquante (NA), les lignes correspondantes ne seront donc pas sélectionnées.

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

    Cela peut s’écrire plus simplement avec un pipe :

    flights |> filter(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 l’on veut uniquement les vols avec un retard au départ (variable dep_delay) compris entre 10 et 15 minutes :

    flights |> 
      filter(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 l’on passe plusieurs arguments à dplyr::filter(), celui-ci rajoute automatiquement une condition ET. La ligne ci-dessus peut donc également être écrite de la manière suivante, avec le même résultat :

    flights |> 
      filter(dep_delay >= 10, dep_delay <= 15)

    Enfin, on peut également placer des fonctions dans les tests, qui nous permettent par exemple de sélectionner les vols avec la plus grande distance :

    flights |> 
      filter(distance == max(distance))
    # A tibble: 342 × 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      857            900        -3     1516           1530
     2  2013     1     2      909            900         9     1525           1530
     3  2013     1     3      914            900        14     1504           1530
     4  2013     1     4      900            900         0     1516           1530
     5  2013     1     5      858            900        -2     1519           1530
     6  2013     1     6     1019            900        79     1558           1530
     7  2013     1     7     1042            900       102     1620           1530
     8  2013     1     8      901            900         1     1504           1530
     9  2013     1     9      641            900      1301     1242           1530
    10  2013     1    10      859            900        -1     1449           1530
    # ℹ 332 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>
    Évaluation contextuelle

    Il est important de noter que dplyr procède à une évaluation contextuelle des expressions qui lui sont passées. Ainsi, on peut indiquer directement le nom d’une variable et dplyr l’interprétera dans le contexte du tableau de données, c’est-à-dire regardera s’il existe une colonne portant ce nom dans le tableau.

    Dans l’expression flights |> filter(month == 1), month est interprété comme la colonne month du tableau flights, à savoir flights$month.

    Il est également possible d’indiquer des objets extérieurs au tableau :

    m <- 2
    flights |> 
      filter(month == m)
    # A tibble: 24,951 × 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     2     1      456            500        -4      652            648
     2  2013     2     1      520            525        -5      816            820
     3  2013     2     1      527            530        -3      837            829
     4  2013     2     1      532            540        -8     1007           1017
     5  2013     2     1      540            540         0      859            850
     6  2013     2     1      552            600        -8      714            715
     7  2013     2     1      552            600        -8      919            910
     8  2013     2     1      552            600        -8      655            709
     9  2013     2     1      553            600        -7      833            815
    10  2013     2     1      553            600        -7      821            825
    # ℹ 24,941 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>

    Cela fonctionne car il n’y a pas de colonne m dans flights. Dès lors, dplyr regarde s’il existe un objet m dans l’environnement de travail.

    Par contre, si une colonne existe dans le tableau, elle aura priorité sur les objets du même nom dans l’environnement. Dans l’exemple ci-dessous, le résultat obtenu n’est pas celui voulu. Il est interprété comme sélectionner toutes les lignes où la colonne mois est égale à elle-même et donc cela sélectionne toutes les lignes du tableau.

    month <- 3
    flights |> 
      filter(month == month)
    # 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     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
    # ℹ 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>

    Afin de distinguer ce qui correspond à une colonne du tableau et à un objet de l’environnement, on pourra avoir recours à .data et .env (voir help(".env", package = "rlang")).

    month <- 3
    flights |> 
      filter(.data$month == .env$month)
    # A tibble: 28,834 × 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     3     1        4           2159       125      318             56
     2  2013     3     1       50           2358        52      526            438
     3  2013     3     1      117           2245       152      223           2354
     4  2013     3     1      454            500        -6      633            648
     5  2013     3     1      505            515       -10      746            810
     6  2013     3     1      521            530        -9      813            827
     7  2013     3     1      537            540        -3      856            850
     8  2013     3     1      541            545        -4     1014           1023
     9  2013     3     1      549            600       -11      639            703
    10  2013     3     1      550            600       -10      747            801
    # ℹ 28,824 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>

    8.1.2 slice()

    Le verbe dplyr::slice() sélectionne des lignes du tableau selon leur position. On lui passe un chiffre ou un vecteur de chiffres.

    Si l’on souhaite sélectionner la 345e ligne du tableau airports :

    airports |> 
      slice(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 l’on veut sélectionner les 5 premières lignes :

    airports |> 
      slice(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…

    8.1.3 arrange()

    dplyr::arrange() réordonne les lignes d’un tableau selon une ou plusieurs colonnes.

    Ainsi, si l’on veut trier le tableau flights selon le retard au départ, dans l’ordre croissant :

    flights |> 
      arrange(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 :

    flights |> 
      arrange(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 l’on veut trier selon une colonne par ordre décroissant, on lui applique la fonction dplyr::desc() :

    flights |> 
      arrange(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 dplyr::slice(), dplyr::arrange() permet par exemple de sélectionner les trois vols ayant eu le plus de retard :

    flights |> 
      arrange(desc(dep_delay)) |> 
      slice(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>

    8.1.4 slice_sample()

    dplyr::slice_sample() permet de sélectionner aléatoirement un nombre de lignes ou une fraction des lignes d’un tableau. Ainsi si l’on veut choisir 5 lignes au hasard dans le tableau airports :

    airports |> 
      slice_sample(n = 5)
    # A tibble: 5 × 8
      faa   name                             lat    lon   alt    tz dst   tzone     
      <chr> <chr>                          <dbl>  <dbl> <dbl> <dbl> <chr> <chr>     
    1 DWH   David Wayne Hooks Field         30.1  -95.6   152    -6 A     America/C…
    2 4G0   Pittsburgh-Monroeville Airport  40.5  -79.8  1187    -5 A     America/N…
    3 ELM   Elmira Corning Rgnl             42.2  -76.9   954    -5 A     America/N…
    4 VLD   Valdosta Regional Airport       30.8  -83.3   203    -5 A     America/N…
    5 FRN   Bryant Ahp                      61.3 -150.    378    -9 A     America/A…

    Si l’on veut tirer au hasard 10% des lignes de flights :

    flights |> 
      slice_sample(prop = .1)
    # A tibble: 33,677 × 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     5    26      757            800        -3      957           1010
     2  2013     3     3     1921           1837        44     2115           2032
     3  2013     7     8     2027           2030        -3     2129           2211
     4  2013    11     5     1613           1620        -7     1854           1935
     5  2013     5    18     1423           1420         3     1651           1700
     6  2013    12    22     1252           1250         2     1604           1610
     7  2013     2    16      635            608        27      943            949
     8  2013    11    15     1905           1856         9     2217           2208
     9  2013    10    16     1551           1600        -9     1842           1906
    10  2013    11    16      821            822        -1     1128           1141
    # ℹ 33,667 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>

    Ces fonctions sont utiles notamment pour faire de l’“échantillonnage” en tirant au hasard un certain nombre d’observations du tableau.

    8.1.5 distinct()

    dplyr::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, dplyr::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 × 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     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
    # ℹ 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>

    8.2 Opérations sur les colonnes

    8.2.1 select()

    dplyr::select() permet de sélectionner des colonnes d’un tableau de données. Ainsi, si l’on veut extraire les colonnes lat et lon du tableau airports :

    airports |> 
      select(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 :

    airports |> 
      select(-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

    dplyr::select() comprend toute une série de fonctions facilitant la sélection de multiples colonnes. Par exemple, dplyr::starts_with(), dplyr::ends_width(), dplyr::contains() ou dplyr::matches() permettent d’exprimer des conditions sur les noms de variables :

    flights |> 
      select(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 incluses3 :

  • 3 À 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.

  • flights |> 
      select(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

    dplyr::all_of() et dplyr::any_of() permettent de fournir une liste de variables à extraire sous forme de vecteur textuel. Alors que dplyr::all_of() renverra une erreur si une variable n’est pas trouvée dans le tableau de départ, dplyr::any_of() sera moins stricte.

    flights |> 
      select(all_of(c("year", "month", "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
    flights |> 
      select(all_of(c("century", "year", "month", "day")))
    Error in `all_of()`:
    ! Can't subset columns that don't exist.
    ✖ Column `century` doesn't exist.
    Erreur : Can't subset columns that don't exist. 
    x Column `century` doesn't exist.
    flights |> 
      select(any_of(c("century", "year", "month", "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

    dplyr::where() permets de sélectionner des variables à partir d’une fonction qui renvoie une valeur logique. Par exemple, pour sélectionner seulement les variables textuelles :

    flights |> 
      select(where(is.character))
    # A tibble: 336,776 × 4
       carrier tailnum origin dest 
       <chr>   <chr>   <chr>  <chr>
     1 UA      N14228  EWR    IAH  
     2 UA      N24211  LGA    IAH  
     3 AA      N619AA  JFK    MIA  
     4 B6      N804JB  JFK    BQN  
     5 DL      N668DN  LGA    ATL  
     6 UA      N39463  EWR    ORD  
     7 B6      N516JB  EWR    FLL  
     8 EV      N829AS  LGA    IAD  
     9 B6      N593JB  JFK    MCO  
    10 AA      N3ALAA  LGA    ORD  
    # ℹ 336,766 more rows

    dplyr::select() peut être utilisée pour réordonner les colonnes d’une table en utilisant la fonction dplyr::everything(), qui sélectionne l’ensemble des colonnes non encore sélectionnées. Ainsi, si l’on souhaite faire passer la colonne name en première position de la table airports, on peut faire :

    airports |> 
      select(name, everything())
    # A tibble: 1,458 × 8
       name                           faa     lat    lon   alt    tz dst   tzone    
       <chr>                          <chr> <dbl>  <dbl> <dbl> <dbl> <chr> <chr>    
     1 Lansdowne Airport              04G    41.1  -80.6  1044    -5 A     America/…
     2 Moton Field Municipal Airport  06A    32.5  -85.7   264    -6 A     America/…
     3 Schaumburg Regional            06C    42.0  -88.1   801    -6 A     America/…
     4 Randall Airport                06N    41.4  -74.4   523    -5 A     America/…
     5 Jekyll Island Airport          09J    31.1  -81.4    11    -5 A     America/…
     6 Elizabethton Municipal Airport 0A9    36.4  -82.2  1593    -5 A     America/…
     7 Williams County Airport        0G6    41.5  -84.5   730    -5 A     America/…
     8 Finger Lakes Regional Airport  0G7    42.9  -76.8   492    -5 A     America/…
     9 Shoestring Aviation Airfield   0P2    39.8  -76.6  1000    -5 U     America/…
    10 Jefferson County Intl          0S9    48.1 -123.    108    -8 A     America/…
    # ℹ 1,448 more rows

    8.2.2 relocate()

    Pour réordonner des colonnes, on pourra aussi avoir recours à dplyr::relocate() en indiquant les premières variables. Il n’est pas nécessaire d’ajouter everything() car avec dplyr::relocate() toutes les variables sont conservées.

    airports |> 
      relocate(lon, lat, name)
    # A tibble: 1,458 × 8
          lon   lat name                           faa     alt    tz dst   tzone    
        <dbl> <dbl> <chr>                          <chr> <dbl> <dbl> <chr> <chr>    
     1  -80.6  41.1 Lansdowne Airport              04G    1044    -5 A     America/…
     2  -85.7  32.5 Moton Field Municipal Airport  06A     264    -6 A     America/…
     3  -88.1  42.0 Schaumburg Regional            06C     801    -6 A     America/…
     4  -74.4  41.4 Randall Airport                06N     523    -5 A     America/…
     5  -81.4  31.1 Jekyll Island Airport          09J      11    -5 A     America/…
     6  -82.2  36.4 Elizabethton Municipal Airport 0A9    1593    -5 A     America/…
     7  -84.5  41.5 Williams County Airport        0G6     730    -5 A     America/…
     8  -76.8  42.9 Finger Lakes Regional Airport  0G7     492    -5 A     America/…
     9  -76.6  39.8 Shoestring Aviation Airfield   0P2    1000    -5 U     America/…
    10 -123.   48.1 Jefferson County Intl          0S9     108    -8 A     America/…
    # ℹ 1,448 more rows

    8.2.3 rename()

    Une variante de dplyr::select() est dplyr::rename()4, qui permet de renommer facilement 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 :

  • 4 Il est également possible de renommer des colonnes directement avec select(), avec la même syntaxe que pour rename().

  • airports |> 
      rename(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 (`) :

    flights |> 
      rename(
        "retard départ" = dep_delay,
        "retard arrivée" = arr_delay
      ) |> 
      select(`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

    8.2.4 rename_with()

    La fonction dplyr::rename_with() permets de renommer plusieurs colonnes d’un coup en transmettant une fonction, par exemple toupper() qui passe tous les caractères en majuscule.

    airports |> 
      rename_with(toupper)
    # A tibble: 1,458 × 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/…
     2 06A   Moton Field Municipal Airport   32.5  -85.7   264    -6 A     America/…
     3 06C   Schaumburg Regional             42.0  -88.1   801    -6 A     America/…
     4 06N   Randall Airport                 41.4  -74.4   523    -5 A     America/…
     5 09J   Jekyll Island Airport           31.1  -81.4    11    -5 A     America/…
     6 0A9   Elizabethton Municipal Airport  36.4  -82.2  1593    -5 A     America/…
     7 0G6   Williams County Airport         41.5  -84.5   730    -5 A     America/…
     8 0G7   Finger Lakes Regional Airport   42.9  -76.8   492    -5 A     America/…
     9 0P2   Shoestring Aviation Airfield    39.8  -76.6  1000    -5 U     America/…
    10 0S9   Jefferson County Intl           48.1 -123.    108    -8 A     America/…
    # ℹ 1,448 more rows

    On pourra notamment utiliser les fonctions du package snakecase et, en particulier, snakecase::to_snake_case() que je recommande pour nommer de manière consistante les variables5.

  • 5 Le snake case est une convention typographique en informatique consistant à écrire des ensembles de mots, généralement, en minuscules en les séparant par des tirets bas.

  • 8.2.5 pull()

    La fonction dplyr::pull() permet d’accéder au contenu d’une variable. C’est un équivalent aux opérateurs $ ou [[]]. On peut lui passer un nom de variable ou bien sa position.

    airports |> 
      pull(alt) |> 
      mean()
    [1] 1001.416
    Note

    dplyr::pull() ressemble à la fonction purrr::chuck() que nous avons déjà abordée (cf. Section 7.4). Cependant, dplyr::pull() ne fonctionne que sur des tableaux de données tandis que purrr::chuck() est plus générique et peut s’appliquer à tous types de listes.

    8.2.6 mutate()

    dplyr::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 airports contient l’altitude de l’aéroport en pieds. Si l’on veut créer une nouvelle variable alt_m avec l’altitude en mètres, on peut faire :

    airports <- 
      airports |> 
      mutate(alt_m = alt / 3.2808)

    On peut créer plusieurs nouvelles colonnes en une seule fois, et les expressions successives peuvent prendre en compte les résultats des calculs précédents. L’exemple suivant convertit d’abord la distance en kilomètres dans une variable distance_km, puis utilise cette nouvelle colonne pour calculer la vitesse en km/h.

    flights <- 
      flights |> 
      mutate(
        distance_km = distance / 0.62137,
        vitesse = distance_km / air_time * 60
    )

    8.3 Opérations groupées

    8.3.1 group_by()

    Un élément très important de dplyr est la fonction dplyr::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 :

    flights |> 
      group_by(month)
    # A tibble: 336,776 × 21
    # 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
    # ℹ 13 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>, 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 dplyr::slice() ou dplyr::mutate() vont en tenir compte lors de leurs opérations.

    Par exemple, si on applique dplyr::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 :

    flights |> 
      group_by(month) |> 
      slice(1)
    # A tibble: 12 × 21
    # 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
    # ℹ 13 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>, distance_km <dbl>,
    #   vitesse <dbl>

    Idem pour dplyr::mutate() : les opérations appliquées lors du calcul des valeurs des nouvelles colonnes sont appliquée groupe de lignes par groupe de lignes. Dans l’exemple suivant, on ajoute une nouvelle colonne qui contient le retard moyen du mois correspondant :

    flights |> 
      group_by(month) |> 
      mutate(mean_delay_month = mean(dep_delay, na.rm = 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     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>, distance_km <dbl>,
    #   vitesse <dbl>, mean_delay_month <dbl>

    Ceci peut permettre, par exemple, de déterminer si un retard donné est supérieur ou inférieur au retard moyen du mois en cours.

    dplyr::group_by() peut aussi être utile avec dplyr::filter(), par exemple pour sélectionner les vols avec le retard au départ le plus important pour chaque mois :

    flights |> 
      group_by(month) |> 
      filter(dep_delay == max(dep_delay, na.rm = TRUE))
    # A tibble: 12 × 21
    # 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    10    14     2042            900       702     2255           1127
     3  2013    11     3      603           1645       798      829           1913
     4  2013    12     5      756           1700       896     1058           2020
     5  2013     2    10     2243            830       853      100           1106
     6  2013     3    17     2321            810       911      135           1020
     7  2013     4    10     1100           1900       960     1342           2211
     8  2013     5     3     1133           2055       878     1250           2215
     9  2013     6    15     1432           1935      1137     1607           2120
    10  2013     7    22      845           1600      1005     1044           1815
    11  2013     8     8     2334           1454       520      120           1710
    12  2013     9    20     1139           1845      1014     1457           2210
    # ℹ 13 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>, distance_km <dbl>,
    #   vitesse <dbl>

    Attention : la clause dplyr::roup_by() marche pour les verbes déjà vus précédemment, sauf pour dplyr::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 × 21
    # 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
    # ℹ 13 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>, distance_km <dbl>,
    #   vitesse <dbl>
    flights |> 
      group_by(month) |> 
      arrange(desc(dep_delay), .by_group = TRUE)
    # A tibble: 336,776 × 21
    # 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
    # ℹ 13 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>, distance_km <dbl>,
    #   vitesse <dbl>

    8.3.2 summarise()

    dplyr::summarise() permet d’agréger les lignes du tableau en effectuant une opération résumée sur une ou plusieurs colonnes. Il s’agit de toutes les fonctions qui prennent en entrée un ensemble de valeurs et renvoie une valeur unique, comme la moyenne (mean()). Par exemple, si l’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 dplyr::group_by(), puisqu’elle permet du coup d’agréger et de résumer les lignes du tableau groupe par groupe. Si l’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 

    dplyr::summarise() dispose d’une fonction spéciale dplyr::n(), qui retourne le nombre de lignes du groupe. Ainsi si l’on veut le nombre de vols par destination, on peut utiliser :

    flights |>
      group_by(dest) |>
      summarise(n = n())
    # 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

    dplyr::n() peut aussi être utilisée avec dplyr::filter() et dplyr::mutate().

    8.3.3 count()

    À noter que quand l’on veut compter le nombre de lignes par groupe, on peut utiliser directement la fonction dplyr::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

    8.3.4 Grouper selon plusieurs variables

    On peut grouper selon plusieurs variables à la fois, il suffit de les indiquer dans la clause du dplyr::group_by() :

    flights |>
      group_by(month, dest) |>
      summarise(nb = n()) |>
      arrange(desc(nb))
    `summarise()` has grouped output by 'month'. You can override using the
    `.groups` argument.
    # A tibble: 1,113 × 3
    # Groups:   month [12]
       month dest     nb
       <int> <chr> <int>
     1     8 ORD    1604
     2    10 ORD    1604
     3     5 ORD    1582
     4     9 ORD    1582
     5     7 ORD    1573
     6     6 ORD    1547
     7     7 ATL    1511
     8     8 ATL    1507
     9     8 LAX    1505
    10     7 LAX    1500
    # ℹ 1,103 more rows

    On peut également compter selon plusieurs variables :

    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 l’on souhaite déterminer le couple origine/destination ayant le plus grand nombre de vols selon le mois de l’année, on devra procéder en deux étapes :

    • d’abord grouper selon mois, origine et destination pour calculer le nombre de vols
    • puis grouper uniquement selon le mois pour sélectionner la ligne avec la valeur maximale.

    Au final, on obtient le code suivant :

    flights |>
      group_by(month, origin, dest) |>
      summarise(nb = n()) |>
      group_by(month) |>
      filter(nb == max(nb))
    `summarise()` has grouped output by 'month', 'origin'. You can override using
    the `.groups` argument.
    # A tibble: 12 × 4
    # Groups:   month [12]
       month origin dest     nb
       <int> <chr>  <chr> <int>
     1     1 JFK    LAX     937
     2     2 JFK    LAX     834
     3     3 JFK    LAX     960
     4     4 JFK    LAX     935
     5     5 JFK    LAX     960
     6     6 JFK    LAX     928
     7     7 JFK    LAX     985
     8     8 JFK    LAX     979
     9     9 JFK    LAX     925
    10    10 JFK    LAX     965
    11    11 JFK    LAX     907
    12    12 JFK    LAX     947

    Lorsqu’on effectue un dplyr::group_by() suivi d’un dplyr::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 groupé par month et origin6 :

  • 6 Comme expliqué dans le message affiché dans la console, cela peut être contrôlé avec l’argument .groups de dplyr::summarise(), dont les options sont décrites dans l’aide de la fonction.

  • flights |>
      group_by(month, origin, dest) |>
      summarise(nb = n())
    `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     nb
       <int> <chr>  <chr> <int>
     1     1 EWR    ALB      64
     2     1 EWR    ATL     362
     3     1 EWR    AUS      51
     4     1 EWR    AVL       2
     5     1 EWR    BDL      37
     6     1 EWR    BNA     111
     7     1 EWR    BOS     430
     8     1 EWR    BQN      31
     9     1 EWR    BTV     100
    10     1 EWR    BUF     119
    # ℹ 2,303 more rows

    Cela peut permettre d’enchaîner les opérations groupées. Dans l’exemple suivant, on calcule le pourcentage des trajets pour chaque destination par rapport à tous les trajets du mois :

    flights |>
      group_by(month, dest) |>
      summarise(nb = n()) |> 
      mutate(pourcentage = nb / sum(nb) * 100)
    `summarise()` has grouped output by 'month'. You can override using the
    `.groups` argument.
    # A tibble: 1,113 × 4
    # Groups:   month [12]
       month dest     nb pourcentage
       <int> <chr> <int>       <dbl>
     1     1 ALB      64     0.237  
     2     1 ATL    1396     5.17   
     3     1 AUS     169     0.626  
     4     1 AVL       2     0.00741
     5     1 BDL      37     0.137  
     6     1 BHM      25     0.0926 
     7     1 BNA     399     1.48   
     8     1 BOS    1245     4.61   
     9     1 BQN      93     0.344  
    10     1 BTV     223     0.826  
    # ℹ 1,103 more rows

    On peut à tout moment dégrouper un tableau à l’aide de dplyr::ungroup(). Ce serait par exemple nécessaire, dans l’exemple précédent, si on voulait calculer le pourcentage sur le nombre total de vols plutôt que sur le nombre de vols par mois :

    flights |>
      group_by(month, dest) |>
      summarise(nb = n()) |> 
      ungroup() |> 
      mutate(pourcentage = nb / sum(nb) * 100)
    `summarise()` has grouped output by 'month'. You can override using the
    `.groups` argument.
    # A tibble: 1,113 × 4
       month dest     nb pourcentage
       <int> <chr> <int>       <dbl>
     1     1 ALB      64    0.0190  
     2     1 ATL    1396    0.415   
     3     1 AUS     169    0.0502  
     4     1 AVL       2    0.000594
     5     1 BDL      37    0.0110  
     6     1 BHM      25    0.00742 
     7     1 BNA     399    0.118   
     8     1 BOS    1245    0.370   
     9     1 BQN      93    0.0276  
    10     1 BTV     223    0.0662  
    # ℹ 1,103 more rows

    À noter que dplyr::count(), par contre, renvoi 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

    8.4 Cheatsheet

    8.5 webin-R

    On pourra également se référer au webin-R #04 (manipuler les données avec dplyr) sur YouTube.