type_data_learning# les lignes de commentaires commencent par #
# cliquer sur alt + entrée à la fin chaque ligne de code pour exécuter la ligne
# première saisie. Il s'agit du très classique jeu de données iris, natif dans R
# le jeu de données s'affiche dans la console
iris
# appel d'une fonction
# nrow() = fonction native de R calculant le nombre de lignes d'un tableau de données
nrow(iris)
# <- permet d'attribuer une valeur à une variable (raccourci R Studio pour <- : alt + 6)
# il y a des bonnes pratiques de nommage des variables : elles sont appliquées dans cette note
<- 1
a a
Pré-requis R
Introduction
La compréhension et la reproduction des scripts PMSI R supposent :
# un environnement R de travail opérationnel avec les packages R appelés dans les scripts (généralement des packages du tidyverse et le package de données refpmsi
# une pratique minimale de R
# de disposer de données PMSI sous forme de tibbles exploitables.
Nous vous invitons à consulter le Guide des scripts
Les explications proposées ci-dessous sont volontairement simplifiées, avec donc quelques abus de langage assumés1
Les supports et ressources en ligne pour apprendre et pratiquer R sont innombrables.
Quelques ressources en français récentes, didactiques et accessibles pour apprendre R :
Introduction à R et au tidyverse par Julien Barnier
analyse-R par Joseph Larmarange
Ressources R et PMSI :
Y a du PMSI dans R
Package refpmsi
Contact pour toute question (avec l’objet “Question formation Data PMSI avec R”)
Installer R
R s’installe sous Windows comme un simple exécutable (comme DRUIDES ou GENRHA par exemple).
Télécharger R dans sa dernière version
Accepter les options par défaut jusqu’à la fin de l’installation.
Nous recommandons une version de R >= à la version 4.1.3 de mars 2022.
Historique des versions de R
Installer R Studio
Après avoir installé R, nous installons R Studio qui est un environnement de développement (IDE) de référence pour R.
Plus exactement, nous allons télécharger la version open source de R Studio, appelée “R Studio Desktop”.
R Studio Desktop s’installe comme un exécutable.
Télécharger R Studio Desktop
Nous recommandons une version de R Studio Desktop >= version 2022.07.02
Historique des versions de R Studio Desktop
A ce stade, vous disposez d’une icône R Studio sur votre bureau pour ouvrir R Studio.
Tuto avec copies écrans pour installer R et R Studio
Tuto pour découvrir R Studio
Autre tuto
Autre IDE pour développer en R : Visual Studio Code
Créer un projet et un premier fichier .R
Créer un premier projet
Nous allons maintenant créer un projet sous R Studio que l’on propose d’appeler formation_data_pmsi
.
Ce projet va regrouper tous les fichiers .R et autres informations en lien avec les exerices, données et scripts de la formation.
Première étape : on crée (à priori à la racine C:), un répertoire avec l’intitulé formation_data_pmsi
.
Seconde étape : dans R Studio, on crée le projet formation_data_pmsi
en le rattachant au répertoire que l’on vient de créer à la première étape via File > New Project > Existing Directory
Un tuto
Autre tuto
Désormais, une fois ouvert R Studio, on ouvrira ce projet formation_data_pmsi
via File > Open Project
Mon premier fichier .R
Nous créons un premier fichier .R dans lequel nous allons sauvegarder les codes R des requêtes et analyses PMSI de la formation.
Pour créer un fichier .R : File > New File > R Script
Un fichier “untitled1” apparaît dans le quadrant haut gauche (le quadrant éditeur de code).
En cliquant sur l’icône “Sauvegarder” de ce quadrant, vous saisissez le nom du fichier, par exemple “intro.R”
Premières lignes de code (à copier/coller)
Penser à sauvegarder votre script R régulièrement et, à minima, avant de quitter R Studio.
En quittant R Studio, ne jamais sauvegarder le .RData si R Studio vous le demande
Contactez-nous pour toute question (avec l’objet “Question formation Data PMSI avec R”)
Minimum de R à connaître
Il y a 4 concepts à connaître : les types de données, les vecteurs, les data frames ou tibbles et les lists
Nous les exposons ci-dessous, à minima, avec des exemples issus de données simili PMSI, à exécuter dans le fichier intro.R
Type de données
Chaque information (un code CIM, un code d’UM, un initulé, une valorisation T2A, un nombre d’actes, la catégorisation d’âge “adulte” versus “moins 18 ans”, un seuil, …) relève d’un type de données.
Il y a 4 types principaux de données (logical, character, integer, numeric) que nous illustrons ci-dessous2
# type logical
# 2 valeurs possibles : TRUE ou FALSE
# exemple. Pour indiquer qu'on excluera les moins de 18 ans d'une analyse
<- FALSE
age_moins_18
age_moins_18
# type character
# valeurs avec du texte. Bien indiquer les ""
<- "S42700"
code_cim
code_cim
# type integer
# valeurs entières
<- 4
seuil_acte
seuil_acte
# type numeric
# valeurs réelles. Avec . au lieu de , pour les décimals
<- 13467.89
valo_t2a valo_t2a
Vecteur
Un vecteur est un ensemble de valeurs du même type.
On parlera ainsi d’un vecteur logique, d’un vecteur character, etc…
# un vecteur est créé par la fonction c()
## ici un vecteur de codes UM
<- c("UM01","UM02","UM03","UM04")
mes_um
mes_um
# nombre d'élements d'un vecteur avec la fonction length()
length(mes_um)
# extraction d'un élément par sa position
## ici extraction du 2eme élément du vecteur
2]
mes_um[
# extraction de plusieurs éléments via un vecteur des positions à extraire
## ici extraction des positions 2 et 4
<- c(2,4)
positions_recherchees
mes_um[positions_recherchees]# ou plus directement
c(2,4)]
mes_um[
# une donnée manquante est indiquée par NA (comme Non Available)
<- c(NA,NA,2,7,NA)
destination_um 1]
destination_UM[3]
destination_UM[
# on peut attribuer un nom à chaque éléments du vecteur avec la fonction names()
<- c("Ortho","Pédiatrie","Gynéco","Urgences")
noms_um names(mes_um) <- noms_um
mes_um
Data frame/tibble
Un data frame ou tableau de données est une liste de vecteurs indépendants.
Un data frame est donc constitué de colonnes de même longueur (même nombre de lignes) qui peuvent être de types différents.
Le jeu de données mini_fake_dataset_mco
, librement téléchargeable (voir ci-dessous), est ainsi un data frame composé de 27 colonnes.
Les référentiels du package de données refpmsi (par exemple le référentiel cim
de la CIM-10 à usage PMSI de 2019 à 2022) sont des data frames.
Abréviation courante : df
Un tibble est un data frame “enrichi” dans l’environnement du tidyverse3.
En pratique, parce qu’on travaille essentiellement avec les packages du tidyverse, on parlera de tibble (abréviation : tbl)
On parlera indifféremment de colonnes ou de variables : une variable d’un tibble correspond à une colonne
List
Une list, au sens R, est une collection de structures de données (valeurs uniques, vecteurs, tibbles, list).
Une image pour visualiser : une list est une commode dont chaque tiroir contient des objects différents, des pulls dans le premier tiroir, des assiettes dans le second tiroir, rien dans le troisième, un seul livre dans le quatrième.
Une list est donc la structure de données la plus souple, la plus puissante, mais aussi la plus complexe à manipuler.
Le jeu de données fake_dataset_mco
des formations MCO est ainsi une list de tibbles (un tbl simili partie fixe des RSS, un tbl simili RSA, un tbl simili actes CCAM, un tble simili DAS, un tbl de DMI, un tbl simili ficium) : nous manipulons donc un seul objet au lieu de 6 objets.
Installer et charger des packages
De manière simplifiée, on peut dire qu’un package est une réunion cohérente de fonctions et de données que l’on va pouvoir utiliser en appelant ses fonctions et ses données sans avoir à se préoccuper de la façon dont elles sont codées.
Une fois installé, un package sera à charger à chaque nouvelle session R Studio.
Les packages d’intérêt général et validés après une série poussée de tests sont disponibles sur le CRAN. C’est essentiellement parmi ces packages que nous allons faire notre marché.
L’installation d’un package est réalisée une fois pour toute (sauf mise à jour du package).
En revanche, à chaque nouvelle session R Studio, nous allons devoir charger les packages nécessaires (voir ci-dessous “Chargement des packages”).
Le tidyverse
Les packages les plus utiles dans les formations Data PMSI avec R sont les packages d’une collection cohérente de packages appelée tidyverse.
Le tidyverse est une sorte méta-package. En chargeant le tidyverse, on charge tous les packages du tidyverse en une fois.
Principaux packages du tidyverse utilisés en analyse PMSI :
- dplyr (package qui fournit les fonctions de base pour résoudre les problèmes de manipulation de données les plus courants comme filtre, trier, sélectionner des colonnes, ajouter une colonne, compter des lignes, …) - tidyr (package pour créer des structures “bien rangées” - tidy en anglais -) - stringr (package pour manipuler des chaînes de caractères) - tibble (package pour manipuler spécifiquement les tibbles) - ggplot2 (package pour produire des graphiques)
Dans le tidyverse, on trouve aussi les packages lubridate (pour manipuler des dates), purrr (pour programmation fonctionnelle), forcats (pour manipuler des facteurs), …
Installation des packages du tidyverse
# suffisant pour les formations [Requêtes MCO], [Requêtes SSR] et [Requêtes PSY]
<- c("tidyverse")
vect_pkg
# la fonction install.packages() installe la dernière version des packages du tidyverse
install.packages(vect_pkg)
Le package refpmsi
refpmsi est un package de référentiels PMSI qui permet de récupérer et travailler avec les référentiels PMSI annualisés et normalisés pour R.
Le chargement de ce package qui n’est pas sur le CRAN est spécifique.
Voir la documentation de refpmsi pour installer refpmsi.
Autres packages CRAN
En fonction des formations Data PMSI avec R, on peut installer d’autres packages du CRAN :
- gt, gtExtras pour les formations [Tableaux]
- ggrepel, ggtext pour les formations [Graphiques]
- data.table pour la formation Requêtes MCO [Avancé]
La liste des packages et fonctions utilisés dans une formation est indiquée dans la présenttion de la formation concernée.
Chargement des packages
Maintenant que nous avons installé les packages nécessaires, nous allons les charger.
Le code ci-dessous est donc à exécuter à chaque nouvelle session de travail, raison pour laquelle on dispose généralement en tête du fichier .R sur lequel on travaille un code, comme celui proposé ci-dessous, pour charger ces packages.
# Charger un package. Ici le package dplyr
library(dplyr)
# Code proposé pour charger rapidement plusieurs packages
# A copier/coller tel quel
# lapply est une fonction qui va "appliquer" la fonction library à chaque élément du vecteur list_packages
# la fonction invisible() est un confort pour ne pas afficher des informations
<- c("dplyr","tibble","tidyr","stringr","jsonlite","refpmsi")
list_packages invisible(lapply(list_packages, library, character.only = TRUE))
# Alternative avec le package pacman
::p_load(char = list_packages) pacman
Charger un jeu de données
La traduction anglaise de jeu de données est dataset. On parlera donc indifféremment désormais de jeux de données ou de dataset.
Pour tester le bon fonctionnement et être opérationnel en début de formation, nous avons construit et mettons à disposition mini_fake_dataset_mco
, un mini jeu de données simili PMSI MCO, cohérent avec les jeux de données mis à disposition pour une formation Data PMSI avec R.
Le jeu mini_fake_dataset_mco
(qui est simplement un fichier texte) est à télécharger librement et à déposer dans un sous-répertoire data
(on pourrait l’appeler autrement) à créer dans le répertoire formation_data_pmsi
.
Puis nous exécutons le code ci-dessous
# On a chargé la suite de packages list_packages : voir étape 5
# Le jeu est chargé dans la variable jeu qui est un dataframe
<- jsonlite::fromJSON("data/mini_fake_dataset_mco.json")
jeu # on vérifie que jeu est bien un data frame avec la fonction is.data.frame()
is.data.frame(jeu)
# pour faciliter son exploitation, on passe ce jeu en tibble avec la fonction as_tibble du package tibble::
# ici on écrase le df jeu par le nouveau tbl jeu qui a le même nom de variable
<- tibble::as_tibble(jeu)
jeu
# on vérifie que le jeu est bien chargé
# la fonction glimpse() du package dplyr fournit un résumé pratique d'un dataset
::glimpse(jeu) dplyr
Le résultat est le suivant :
Rows: 30
Columns: 27
$ ghm <chr> "06M041", "04M05T", "04M203~
$ code_retour <chr> "000", "000", "000", "000",~
$ nas <chr> "1740", "435", "1684", "125~
$ no_rum <chr> "1", "1", "1", "1", "1", "1~
$ age <int> 72, 58, 59, 55, 71, 87, 65,~
$ sexe <chr> "F", "F", "H", "F", "F", "H~
$ no_um <chr> "um01", "um01", "um01", "um~
$ type_aut_lit_dedie <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ mode_entree_um <chr> "8", "8", "8", "8", "8", "8~
$ provenance_um <chr> "5", "5", "5", "5", "5", "5~
$ mode_sortie_um <chr> "6", "8", "6", "8", "8", "6~
$ destination_um <chr> "1", "NA", "1", "NA", "NA",~
$ nb_seances <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
$ nb_das <int> 1, 3, 1, 0, 0, 0, 0, 1, 1, ~
$ nb_ccam <int> 0, 3, 3, 3, 3, 5, 2, 3, 1, ~
$ dp <chr> "K625", "J181", "J9600", "N~
$ dr <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ igs_2 <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
$ confirmation_codage_rss <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ conversion_hc <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ raac <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ contexte_patient_surveillance_particuliere <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ admin_produit_rh <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ rescrit_tarifaire <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ cat_nb_inter_tot <lgl> NA, NA, NA, NA, NA, NA, NA,~
$ date_entree_um <chr> "2022-07-01", "2022-03-01",~
$ date_sortie_um <chr> "2022-07-02", "2022-03-02",~
Pour les formations, nous mettons à disposition des participants le jeu de données fake_dataset_mco
plus fourni avec plus de lignes et différents tibbles.
Nous recommandons aux participants médecins DIM de récupérer les données PMSI de leurs établissements au format JSON via l’accès Standard de PMSISoft
Les noms des variables de nos fake dataset PMSI sont ceux des exports de l’accès Standard de PMSISoft en JSON : les médecins DIM peuvent donc ainsi coder en R, pendant la formation, sur les données PMSI de leurs établissements.
Le pipe %>%
et son fonctionnement
Comprendre ce qu’est et comment fonctionne le pipe %>%
est fondamental.
C’est ce qui permet de construire des scripts lisibles, complexes, testables et maintenables.
L’idée de base est la suivante : puisque, pour la quasi-totalité des fonctions R et spécialement pour les fonctions du tidyverse
, le premier argument de ces fonctions est un data frame (sur lequel va s’appliquer la fonction)4 et qu’un script consiste, dans son principe, à enchaîner des traitements successifs, on va passer directement le résultat de chaque traitement (qui est donc un tibble modifié) au traitement suivant via le pipe %>%
Illustrons avec le mini_fake_dataset_mco
que nous avons chargé à l’étape 6 en lui appliquant quelques traitements simples (voir étape 8 “Quelques manipulations simples” ci-dessous).
Première approche sans le %>%
: on enregistre le résultat de chaque traitement dans une variable
# on reprend la variable jeu créée lors de l'étape 6
# premier traitement : on filtre les RUM groupé en 04M023 avec la fonction filter() du package dplyr
# on préfixe les fonctions avec leur package en codant dplyr::filter()
# on pourrait coder aussi filter() sans référence au package
# on constate que le premier argument de la fonction filter() est bien un data frame,
# ici jeu qui est notre jeu de données
<- dplyr::filter(jeu, ghm == "04M203")
jeu1
jeu1
# second traitement : on sélectionne quelques variables
<- dplyr::select(jeu1, ghm,nas,no_rum,age,dp,dr,nb_das,nb_ccam,date_entree_um,date_sortie_um)
jeu2
jeu2
# troisième traitement : on transforme les 2 variables date_entree_um et date_sortie_um au format date
<- dplyr::mutate(jeu2, date_entree_um = as.Date(date_entree_um),
jeu3 date_sortie_um = as.Date(date_sortie_um))
jeu3
# 4eme traitement : on créé la variable cmd en récupérant les 2 premières positions du ghm
<- dplyr::mutate(jeu3, cmd = stringr::str_sub(ghm,1,2))
jeu4 jeu4
Constat :
On a un tibble d’entrée (jeu
) et on veut un tibble résultat.
Avec cette approche, on génère 4 tibble pour arriver au résultat voulu.
Sachant qu’un script classique PMSI (exemple : produire un case mix simple) va se composer d’une dizaine de traitements et qu’on enchaîne souvent plusieurs suites de traitements, on voit bien que cela devient très rapidement ingérable et illisible avec des dizaines de résultats intermédiaires et des risques constants d’erreur de saisie.
Deuxième approche : composition de fonctions
# on reprend les 4 traitements de la 1ère approche
# en partant du dernier traitement dont le tibble est le résultat
# puis du 3eme traitement, etc...
::mutate(dplyr::mutate(dplyr::select(dplyr::filter(jeu, ghm == "04M203"), ghm,nas,no_rum,age,dp,dr,nb_das,nb_ccam,date_entree_um,date_sortie_um),
dplyrdate_entree_um = as.Date(date_entree_um),
date_sortie_um = as.Date(date_sortie_um)),
cmd = stringr::str_sub(ghm,1,2))
Constat : Cela se passe de commentaires !
L’approche avec le pipe `%>%
# le tibble final est directement enregistré dans une variable que l'on nomme ici jeu_resultat
# le raccourci R Studio pour le pipe %>% est ctrl + shift (la flêche vers le haut) + M
<- dplyr::filter(jeu, ghm == "04M203") %>%
jeu_resultat # dans la fonction dplyr::select(), il n'y a plus de premier argument affiché
# car le pipe a transféré dans le premier argument de la fonction dplyr::select() le tibble
# issu du traitement de la ligne précédente
::select(ghm,nas,no_rum,age,dp,dr,nb_das,nb_ccam,date_entree_um,date_sortie_um) %>%
dplyr# même fonctionnement avec la fonction dplyr::mutate() dont le premier argument "invisible"
# est le tibble produit par ce qui précède le %>%
# la fonction dplyr::mutate() permet de créer ou modifier des variables
::mutate(date_entree_um = as.Date(date_entree_um),
dplyrdate_sortie_um = as.Date(date_sortie_um)) %>%
# la fonction strinr::str_sub() permet d'extraire une partie d'une suite de caractères
::mutate(cmd = stringr::str_sub(ghm,1,2))
dplyr
jeu_resultat
# si je veux uniquement les 2 premiers traitements
# je mets en commentaire les lignes inutilisées : très souple pour "jouer" avec un script
<- dplyr::filter(jeu, ghm == "04M203") %>%
jeu_resultat ::select(ghm,nas,no_rum,age,dp,dr,nb_das,nb_ccam,date_entree_um,date_sortie_um)
dplyr# dplyr::mutate(jeu2, date_entree_um = as.Date(date_entree_um), date_sortie_um = as.Date(date_sortie_um)) %>%
# dplyr::mutate(jeu3, cmd = stringr::str_sub(ghm,1,2))
jeu_resultat
# autre intérêt : je réitère très facilement pour un autre ghm
# en changeant juste à un seul endroit (dans le filter) le code ghm
<- dplyr::filter(jeu, ghm == "19M024") %>%
jeu_resultat ::select(ghm,nas,no_rum,age,dp,dr,nb_das,nb_ccam,date_entree_um,date_sortie_um) %>%
dplyr::mutate(date_entree_um = as.Date(date_entree_um), date_sortie_um = as.Date(date_sortie_um)) %>%
dplyr::mutate(cmd = stringr::str_sub(ghm,1,2))
dplyr jeu_resultat
Constat :
Le code est lisible : on voit bien ce qui se passe dans chaque ligne.
Je peux documenter chaque ligne.
Je n’ai que 2 tibble : le tibble d’origine qui ne bouge pas et le tibble résultat.
Je peux tester une suite de lignes de code en supprimant le pipe à l’endroit voulu.
Je peux modifier un traitement sans modifier les autres ni tout reprendre (manipulation très fréquente en PMSI où on va tester des hypothèses et des codages à la volée).
Quelques manipulations simples
A partir du jeu mini_fake_dataset_mco
que nous avons chargé à l’étape 6, quelques manipulations basiques avec des fonctions du tidyverse permettant de voir aussi le fonctionnement du pipe %>%
fonction dplyr::filter()
Pour filtrer des lignes5
# filter() fonctionne avec les valeurs logiques.
# ici no_um == "um01" teste cette condition sur chaque ligne, donc avec une réponse attendue TRUE ou FALSE
# si le code UM est bien "um01", no_um == "um01 produit la valeur TRUE et donc filter retient la ligne
%>% dplyr::filter(no_um == "um01")
jeu
# 2 filtrages successives
%>%
jeu ::filter(no_um == "um01") %>%
dplyr::filter(age >= 75)
dplyr# ou plus directement les 2 filtrages dans un seul traitement où & est le ET logique
%>% dplyr::filter(no_um == "um01" & age >= 75) jeu
fonction dplyr::select()
Pour sélectionner des variables
# Sélection de quelques variables par leur nom
%>% dplyr::select(ghm,nas,no_rum,dp)
jeu # en PMSI, on a souvent beaucoup de colonnes.
# on verra dans la formation comment sélectionner intelligemment parmi beaucoup de variables
fonction dplyr::mutate()
Pour ajouter ou modifier des variables
# création d'un variable cmd
%>% dplyr::mutate(cmd = stringr::str_sub(ghm,1,2)) jeu
fonction dplyr::arrange()
Pour trier selon une ou plusieurs colonnes
# Tri ascendant sur l'âge après sélection de variables
%>%
jeu ::select(ghm,nas,no_rum,no_um,dp,age) %>%
dplyr::arrange(age)
dplyr# tri descendant avec l'option desc() dans arrange()
%>%
jeu ::select(ghm,nas,no_rum,no_um,dp,age) %>%
dplyr::arrange(desc(age)) dplyr
exercices
Codes CIM-10 autorisés en DP
# Récupération du référentiel CIM-10
<- refpmsi::refpmsi("cim")
cim_10 ::glimpse(cim_10)
dplyr
<- cim_10 %>%
cim_dp_2022 # sélection des variables qui nous intéressent
::select(cim_code,cim_tmco,annee_pmsi,cim_lib) %>%
dplyr::filter(annee_pmsi == "2022") %>%
dplyr# rappel : les codes autorisés en DP ont la valeur 0
# (voir le kit de la nomenclature CIM PMSI sur le site de l'ATIH)
::filter(cim_tmco == 0)
dplyr# résultat : 13 357 codes
%>% View
cim_dp_2022
# Et les codes CIM-10 non autorisés en DP
<- cim_10 %>%
cim__non_dp_2022 ::select(cim_code,cim_tmco,annee_pmsi,cim_lib) %>%
dplyr::filter(annee_pmsi == "2022") %>%
dplyr::filter(cim_tmco != 0)
dplyr%>% View cim_non_dp_2022
RUM le plus long d’une sous CMD
<- jeu %>%
jeu1 ::select(nas,no_rum,ghm,date_sortie_um,date_entree_um) %>%
dplyr::mutate(sous_cmd = stringr::str_sub(ghm,1,3)) %>%
dplyr::mutate(date_sortie_um = as.Date(date_sortie_um), date_entree_um = as.Date(date_entree_um)) %>%
dplyr::mutate(duree_rum = date_sortie_um - date_entree_um) %>%
dplyr::filter(sous_cmd == "04M") %>%
dplyr::mutate(duree_rum = date_sortie_um - date_entree_um) %>%
dplyr::filter(duree_rum == max(duree_rum))
dplyr# résultat : le rum 2 du nas 411 avec 34 journées PMSI
jeu1
Contact pour toute question (avec l’objet “Question formation Data PMSI avec R”)
Notes de bas de page
par exemple, on ne distingue pas les notions de types, modes et classes de données, mais on se réfère au sens courant du mot type de données.↩︎
il y a aussi les données
Date
par exemple↩︎on ne discutera pas ici des différences entre df et tbl↩︎
voir par exemple la documenter de la fonction très courante dplyr::filter où le premier argument (.data) est bien le data frame sur lequel le filter va s’appliquer.↩︎