dplyrFormation en R
Dans ce module, nous apprendrons comment manipuler (nettoyer, transformer et préparer) des données fiscales en utilisant dplyr.
Que signifie “manipulation de données” ?
La manipulation de données est le processus de transformation de données brutes en un format prêt pour l’analyse.
Pensez-y comme préparer des ingrédients avant de cuisiner :
À la fin de ce module, vous pourrez :
dplyr ?dplyr fait partie du tidyverse - une collection de paquets R conçus pour travailler ensemble de manière transparente.
Avantages :
✅ Lisible - les verbes correspondent à ce que vous voulez faire
✅ Cohérent - syntaxe similaire pour toutes les opérations
✅ Adapté aux débutants - clair et logique
✅ Bien documenté - tonnes de ressources
Note
Nous expliquerons ce que signifie %>% dans un moment !
Avant de plonger dans la manipulation de données, nous devons comprendre un concept crucial :
Les Modifications Ne Sont Pas Sauvegardées Sauf Si Vous Les Sauvegardez !
Lorsque vous transformez des données dans R, les modifications NE sont PAS sauvegardées automatiquement. Vous devez utiliser l’opérateur d’affectation <- pour stocker les résultats.
Créez un NOUVEL objet quand :
Écrasez le MÊME objet quand :
L’opérateur d’affectation <- a un raccourci clavier :
Astuce
Alt + - (moins) (Windows/Linux)
Option + - (moins) (Mac)
Cela écrit <- automatiquement !
%>%L’opérateur pipe (%>%) est la clé pour écrire du code clair et lisible.
Pensez-y comme “et puis” :
Comment le lire :
tax_data%>%) filtrer à 2023%>%) sélectionner des colonnes spécifiques%>%) trier les résultatsAstuce
Raccourci clavier : Ctrl + Shift + M (Windows) ou Cmd + Shift + M (Mac)
Comprenons les pipes avec un exemple quotidien :
Faire du café (sans pipes) :
Faire du café (avec pipes) :
filter()filter() sélectionne des lignes basées sur des conditions :
[1] 339
Opérateurs de comparaison courants :
== égal à!= différent de> plus grand que< plus petit que>= plus grand ou égal à<= plus petit ou égal àUtiliser des virgules ou & pour AND (toutes les conditions doivent être vraies) :
[1] 71
%in%Vérifier si les valeurs correspondent à une liste :
character(0)
Vous pouvez trouver l’exercice dans le dossier “Exercises/exercise_01_template.R”
10:00 Vos tâches :
En utilisant panel_vat :
vat_outputs > 30000Indice : Pour le bonus, utilisez group_by(), summarize(), arrange(), et head()
# 1. Filtrer grands outputs
grands_outputs <- panel_vat %>%
filter(vat_outputs > 30000)
nrow(grands_outputs)
# 2. Filtrer T1 de 2023
q1_2023 <- panel_vat %>%
filter(filing_year == 2023, filing_quarter == 1)
nrow(q1_2023)
# 3. TVA nette négative
tva_negative <- panel_vat %>%
filter(vat_outputs - vat_inputs < 0)
nrow(tva_negative)
# 4. Bonus : Top 5 entreprises
top_firms <- panel_vat %>%
group_by(firm_id) %>%
summarize(total_vat = sum(vat_outputs, na.rm = TRUE), .groups = "drop") %>%
arrange(desc(total_vat)) %>%
head(5)
# Déclarations de ces entreprises
declarations_top <- panel_vat %>%
filter(firm_id %in% top_firms$firm_id)select()select() choisit quelles colonnes conserver :
[1] "firm_id" "declaration_date" "vat_outputs" "vat_inputs"
Sélectionner des colonnes par motif :
[1] "vat_inputs" "vat_outputs"
Vous pouvez renommer des colonnes dans select() :
[1] "empresa" "fecha" "iva_cobrado" "iva_pagado"
mutate()mutate() est votre outil le plus important - crée ou modifie des colonnes :
firm_id vat_outputs vat_inputs net_vat
<char> <int> <int> <int>
1: FIRM_0096 45914 45262 652
2: FIRM_0081 29661 9225 20436
3: FIRM_0024 10005 15289 -5284
Créer plusieurs colonnes à la fois :
firm_id net_vat vat_ratio is_large
<char> <int> <num> <lgcl>
1: FIRM_0096 652 0.9857995 TRUE
2: FIRM_0081 20436 0.3110145 FALSE
3: FIRM_0024 -5284 1.5281359 FALSE
Astuce
Vous pouvez référencer des colonnes nouvellement créées dans la même instruction mutate !
if_else()Créer des colonnes basées sur des conditions :
firm_id vat_outputs taxpayer_size
<char> <int> <char>
1: FIRM_0096 45914 Grand
2: FIRM_0081 29661 Petit
3: FIRM_0024 10005 Petit
case_when()Pour plus de 2 catégories, utilisez case_when() :
firm_id vat_outputs size_category
<char> <int> <char>
1: FIRM_0096 45914 Grand
2: FIRM_0081 29661 Moyen
3: FIRM_0024 10005 Petit
4: FIRM_0091 14410 Petit
5: FIRM_0014 33378 Moyen
Vous pouvez trouver l’exercice dans le dossier “Exercises/exercise_02_template.R”
10:00 Vos tâches :
En utilisant panel_vat :
net_vat (vat_outputs - vat_inputs)vat_ratio (vat_inputs / vat_outputs)is_refund (vrai si net_vat < 0)compliance_status :
Bonus : Créer days_to_file calculant les jours entre declaration_date et la fin de filing_quarter
# Charger les paquets
library(dplyr)
library(lubridate)
# Créer des variables
vat_ameliore <- panel_vat %>%
mutate(
# 1. TVA nette
net_vat = vat_outputs - vat_inputs,
# 2. Ratio de TVA
vat_ratio = vat_inputs / vat_outputs,
# 3. Drapeau de remboursement
is_refund = if_else(net_vat < 0, TRUE, FALSE),
# 4. Statut de conformité
compliance_status = case_when(
vat_ratio > 0.95 ~ "Risque élevé",
vat_ratio > 0.80 ~ "Risque modéré",
TRUE ~ "Risque faible"
)
)
# Bonus : Jours pour déclarer
vat_ameliore <- vat_ameliore %>%
mutate(
quarter_end = ceiling_date(declaration_date, "quarter") - days(1),
days_to_file = as.numeric(declaration_date - quarter_end)
)
# Vérifier les résultats
vat_ameliore %>%
select(firm_id, net_vat, vat_ratio, is_refund, compliance_status) %>%
head(5)arrange()arrange() trie les lignes par colonnes :
firm_id vat_outputs
<char> <int>
1: FIRM_0066 1014
2: FIRM_0044 1045
3: FIRM_0020 1073
4: FIRM_0032 1110
5: FIRM_0072 1168
Trier en ordre décroissant avec desc() :
Trier par plusieurs colonnes :
firm_id filing_year vat_outputs
<char> <int> <int>
1: FIRM_0001 2021 24343
2: FIRM_0002 2021 26706
3: FIRM_0002 2021 3018
4: FIRM_0003 2021 29978
5: FIRM_0003 2021 7239
Astuce
L’ordre compte ! R trie par la première colonne, puis départage avec la deuxième, etc.
summarize()summarize() réduit les données en résumés :
total_vat avg_vat max_vat num_declarations
1 25883247 25883.25 49969 1000
Fonctions de résumé utiles :
sum() - totalmean() - moyennemedian() - médianesd() - écart-typemin(), max() - minimum, maximumn() - compter les lignesn_distinct() - compter les valeurs uniquesgroup_by()Le vrai pouvoir vient de group_by() + summarize() :
# A tibble: 3 × 4
filing_year total_vat avg_vat num_firms
<int> <int> <dbl> <int>
1 2021 8582818 26088. 96
2 2022 8436159 25410. 95
3 2023 8864270 26148. 97
Important
Ajoutez toujours .groups = "drop" après summarize pour éviter des problèmes !
Regrouper par plusieurs variables :
# A tibble: 8 × 4
filing_year filing_quarter total_vat num_declarations
<int> <int> <int> <int>
1 2021 1 1870290 72
2 2021 2 2127706 77
3 2021 3 2446393 95
4 2021 4 2138429 85
5 2022 1 2317221 90
6 2022 2 1925538 78
7 2022 3 2352286 86
8 2022 4 1841114 78
count()Pour seulement compter, count() est plus simple :
filing_year n
<int> <int>
1: 2021 329
2: 2022 332
3: 2023 339
Avec plusieurs variables :
group_by() fonctionne aussi avec mutate() :
# Calculer la part d'entreprise de la TVA trimestrielle
vat_with_share <- panel_vat %>%
group_by(filing_quarter) %>%
mutate(
quarter_total = sum(vat_outputs, na.rm = TRUE),
firm_share = vat_outputs / quarter_total * 100
) %>%
ungroup() # Toujours dégrouper après !
vat_with_share %>%
select(firm_id, filing_quarter, vat_outputs, firm_share) %>%
head(5)# A tibble: 5 × 4
firm_id filing_quarter vat_outputs firm_share
<chr> <int> <int> <dbl>
1 FIRM_0096 1 45914 0.697
2 FIRM_0081 2 29661 0.471
3 FIRM_0024 1 10005 0.152
4 FIRM_0091 3 14410 0.200
5 FIRM_0014 3 33378 0.464
Avertissement
Utilisez toujours ungroup() après des opérations groupées avec mutate !
lubridate facilite le travail avec les dates :
[1] 2023
[1] 3
[1] 15
[1] 1
[1] 4
Modèle courant pour les données fiscales :
# Ajouter des composants de date utiles
vat_with_dates <- panel_vat %>%
mutate(
filing_year = year(declaration_date),
filing_quarter = quarter(declaration_date),
filing_month = month(declaration_date),
filing_day = day(declaration_date),
filing_weekday = wday(declaration_date)
)
vat_with_dates %>%
select(declaration_date, filing_year, filing_quarter, filing_month, filing_weekday) %>%
head(3) declaration_date filing_year filing_quarter filing_month filing_weekday
<Date> <int> <int> <int> <int>
1: 2023-01-31 2023 1 1 3
2: 2022-05-31 2022 2 5 3
3: 2023-03-31 2023 1 3 6
Calculer des différences de date :
# Jours depuis la dernière déclaration par entreprise
vat_with_gaps <- panel_vat %>%
arrange(firm_id, declaration_date) %>%
group_by(firm_id) %>%
mutate(
days_since_last = as.numeric(declaration_date - lag(declaration_date))
) %>%
ungroup()
vat_with_gaps %>%
select(firm_id, declaration_date, days_since_last) %>%
filter(!is.na(days_since_last)) %>%
head(5)# A tibble: 5 × 3
firm_id declaration_date days_since_last
<chr> <date> <dbl>
1 FIRM_0001 2022-03-31 335
2 FIRM_0001 2022-05-31 61
3 FIRM_0001 2022-08-31 92
4 FIRM_0001 2022-10-31 61
5 FIRM_0001 2023-04-30 181
Astuce
lag() obtient la valeur de la ligne précédente dans chaque groupe !
[1] "2023-03-01"
[1] "2023-04-01"
[1] "2023-01-01"
distinct()Obtenir des lignes uniques :
[1] 100
slice()Obtenir des lignes spécifiques :
firm_id declaration_date
<char> <Date>
1: FIRM_0096 2023-01-31
2: FIRM_0081 2022-05-31
3: FIRM_0024 2023-03-31
4: FIRM_0091 2023-08-31
5: FIRM_0014 2023-09-30
Top/Bottom par groupe :
# A tibble: 3 × 8
firm_id declaration_date vat_inputs vat_outputs reimbursement_date filing_year
<chr> <date> <int> <int> <date> <int>
1 FIRM_0… 2023-10-31 2032 49327 2022-01-31 2023
2 FIRM_0… 2023-07-31 42580 44400 2022-02-28 2023
3 FIRM_0… 2023-04-30 11753 47713 2022-09-30 2023
# ℹ 2 more variables: filing_quarter <int>, filing_month <int>
slice_sample()Échantillonnage aléatoire pour l’analyse :
firm_id vat_outputs
<char> <int>
1: FIRM_0077 29739
2: FIRM_0072 5627
3: FIRM_0095 36992
4: FIRM_0075 10066
5: FIRM_0044 9112
relocate()Déplacer les colonnes vers des positions spécifiques :
[1] "firm_id" "declaration_date" "vat_inputs"
[4] "vat_outputs" "reimbursement_date"
Le vrai pouvoir de dplyr vient de combiner des opérations dans une séquence logique :
# Exemple de flux de travail complet
analysis_result <- panel_vat %>%
# Étape 1 : Calculer de nouvelles variables
mutate(
net_vat = vat_outputs - vat_inputs,
filing_quarter = quarter(declaration_date)
) %>%
# Étape 2 : Filtrer sur données récentes
filter(filing_year == 2023) %>%
# Étape 3 : Analyser par trimestre
group_by(filing_quarter) %>%
summarize(
total_vat = sum(net_vat, na.rm = TRUE),
avg_vat = mean(net_vat, na.rm = TRUE),
num_firms = n_distinct(firm_id),
.groups = "drop"
)
analysis_result# A tibble: 4 × 4
filing_quarter total_vat avg_vat num_firms
<int> <int> <dbl> <int>
1 1 442405 5395. 54
2 2 15185 167. 59
3 3 -104600 -1113. 62
4 4 179021 2486. 49
Parfois, il est préférable de diviser de longs pipelines en morceaux plus petits :
Bon pour les flux de travail complexes :
# Étape 1 : Ajouter des variables dérivées
vat_enhanced <- panel_vat %>%
mutate(
net_vat = vat_outputs - vat_inputs,
filing_quarter = quarter(declaration_date)
)
# Étape 2 : Analyser
vat_summary <- vat_enhanced %>%
group_by(filing_year, filing_quarter) %>%
summarize(avg_vat = mean(net_vat, na.rm = TRUE), .groups = "drop")
head(vat_summary)# A tibble: 6 × 3
filing_year filing_quarter avg_vat
<int> <int> <dbl>
1 2021 1 -519.
2 2021 2 2447.
3 2021 3 219.
4 2021 4 442.
5 2022 1 100.
6 2022 2 -1321.
Astuce
Diviser en étapes quand :
Construisez votre analyse avec des colonnes calculées significatives :
# Créer un jeu de données enrichi avec de nombreuses variables dérivées
panel_vat_enhanced <- panel_vat %>%
mutate(
# Calculs financiers
net_vat = vat_outputs - vat_inputs,
vat_ratio = vat_inputs / vat_outputs,
# Drapeaux de logique métier
is_refund = if_else(net_vat < 0, TRUE, FALSE),
large_taxpayer = if_else(vat_outputs > 40000, TRUE, FALSE),
high_ratio = if_else(vat_ratio > 0.9, TRUE, FALSE, missing = FALSE)
)
# Vérifier ce que nous avons créé
panel_vat_enhanced %>%
select(firm_id, net_vat, is_refund, large_taxpayer, high_ratio) %>%
head(5) firm_id net_vat is_refund large_taxpayer high_ratio
<char> <int> <lgcl> <lgcl> <lgcl>
1: FIRM_0096 652 FALSE TRUE TRUE
2: FIRM_0081 20436 FALSE FALSE FALSE
3: FIRM_0024 -5284 TRUE FALSE TRUE
4: FIRM_0091 5063 FALSE FALSE FALSE
5: FIRM_0014 -13939 TRUE FALSE TRUE
Sauvegardez vos jeux de données améliorés pour utilisation dans les modules ultérieurs :
# Sauvegarder le panel TVA amélioré dans le dossier Clean
panel_vat_clean <- panel_vat %>%
mutate(
net_vat = vat_outputs - vat_inputs,
filing_quarter = quarter(declaration_date),
is_refund = net_vat < 0,
large_taxpayer = vat_outputs > 40000
)
fwrite(panel_vat_clean,
here("r_training_datax", "Exercises", "data", "Clean", "panel_vat_clean.csv"))
# Sauvegarder le panel CIT amélioré dans le dossier Clean
panel_cit_clean <- panel_cit %>%
mutate(
filing_quarter = quarter(declaration_date),
effective_tax_rate = tax_paid / taxable_income
)
fwrite(panel_cit_clean,
here("r_training_datax", "Exercises", "data", "Clean", "panel_cit_clean.csv"))Gardez vos fichiers organisés :
r_training_datax/
└── Exercises/
└── data/
├── Raw/ # Données originales, non touchées
│ ├── firm_characteristics.csv
│ ├── vat_declarations.dta
│ └── cit_declarations.xlsx
├── intermediate/ # Après nettoyage du Module 2
│ ├── dt_firms.csv
│ ├── panel_vat.csv
│ └── panel_cit.csv
└── Clean/ # Après transformation du Module 3
├── panel_vat_clean.csv
└── panel_cit_clean.csv
Astuce
Sauvegardez les versions améliorées dans le dossier Clean pour pouvoir les utiliser dans les modules futurs !
Vous pouvez trouver l’exercice dans le dossier “Exercises/exercise_03_template.R”
15:00 Vos tâches :
Créez des jeux de données complètement transformés prêts pour l’analyse :
net_vat, filing_year, filing_quarter, filing_monthvat_ratio et days_since_last par entrepriseis_refund, large_taxpayer (>40000), high_ratio (>0.9)data/Clean/panel_vat_clean.csv en utilisant fwrite()filing_year, filing_quartereffective_tax_rate (tax_paid / taxable_income)has_adjustments (adjustments != 0)data/Clean/panel_cit_clean.csv en utilisant fwrite()clean_names()data/Clean/dt_firms_clean.csv en utilisant fwrite()file.exists()names() et glimpse()Rappel : Ces jeux de données nettoyés seront utilisés dans les Modules 4, 5 et 6 !
# Charger les paquets requis
library(dplyr)
library(lubridate)
library(data.table)
library(here)
library(janitor)
# Charger les données depuis le dossier intermediate
panel_vat <- fread(here("r_training_datax", "Exercises", "data", "intermediate", "panel_vat.csv"))
panel_cit <- fread(here("r_training_datax", "Exercises", "data", "intermediate", "panel_cit.csv"))
dt_firms <- fread(here("r_training_datax", "Exercises", "data", "intermediate", "dt_firms.csv"))
# Convertir les dates
panel_vat$declaration_date <- as.Date(panel_vat$declaration_date)
panel_cit$declaration_date <- as.Date(panel_cit$declaration_date)
# 1. Transformer panel_vat
panel_vat_clean <- panel_vat %>%
# Ajouter des composants de date
mutate(
filing_year = year(declaration_date),
filing_quarter = quarter(declaration_date),
filing_month = month(declaration_date)
) %>%
# Calculer des métriques financières
mutate(
net_vat = vat_outputs - vat_inputs,
vat_ratio = vat_inputs / vat_outputs
) %>%
# Créer des drapeaux métier
mutate(
is_refund = if_else(net_vat < 0, TRUE, FALSE),
large_taxpayer = if_else(vat_outputs > 40000, TRUE, FALSE),
high_ratio = if_else(vat_ratio > 0.9, TRUE, FALSE, missing = FALSE)
) %>%
# Calculer les jours entre déclarations par entreprise
arrange(firm_id, declaration_date) %>%
group_by(firm_id) %>%
mutate(days_since_last = as.numeric(declaration_date - lag(declaration_date))) %>%
ungroup()
# Sauvegarder dans le dossier Clean
fwrite(panel_vat_clean,
here("r_training_datax", "Exercises", "data", "Clean", "panel_vat_clean.csv"))
# 2. Transformer panel_cit
panel_cit_clean <- panel_cit %>%
# Ajouter des composants de date
mutate(
filing_year = year(declaration_date),
filing_quarter = quarter(declaration_date)
) %>%
# Calculer des métriques financières
mutate(
effective_tax_rate = tax_paid / taxable_income
) %>%
# Créer des drapeaux métier
mutate(
has_adjustments = if_else(adjustments != 0, TRUE, FALSE)
)
# Sauvegarder dans le dossier Clean
fwrite(panel_cit_clean,
here("r_training_datax", "Exercises", "data", "Clean", "panel_cit_clean.csv"))
# 3. Transformer dt_firms
dt_firms_clean <- dt_firms %>%
clean_names()
# Sauvegarder dans le dossier Clean
fwrite(dt_firms_clean,
here("r_training_datax", "Exercises", "data", "Clean", "dt_firms_clean.csv"))
# 4. Vérifier le travail
file.exists(here("r_training_datax", "Exercises", "data", "Clean", "panel_vat_clean.csv"))
file.exists(here("r_training_datax", "Exercises", "data", "Clean", "panel_cit_clean.csv"))
file.exists(here("r_training_datax", "Exercises", "data", "Clean", "dt_firms_clean.csv"))
# Les recharger
vat_verify <- fread(here("r_training_datax", "Exercises", "data", "Clean", "panel_vat_clean.csv"))
cit_verify <- fread(here("r_training_datax", "Exercises", "data", "Clean", "panel_cit_clean.csv"))
firms_verify <- fread(here("r_training_datax", "Exercises", "data", "Clean", "dt_firms_clean.csv"))
# Vérifier les colonnes
names(vat_verify)
names(cit_verify)
names(firms_verify)
# Résumé rapide
glimpse(vat_verify)
glimpse(cit_verify)
glimpse(firms_verify)Verbes centraux de dplyr :
filter() - sélectionner des lignesselect() - choisir des colonnesmutate() - créer/modifier des colonnesarrange() - trier les donnéessummarize() + group_by() - agrégercount() - fréquencesdistinct() - supprimer les doublonsOpérations avec dates :
lubridate✅ Utilisez toujours les pipes (%>%) pour enchaîner clairement les opérations
✅ Sauvegardez votre travail avec <- pour les variables que vous réutiliserez
✅ Incluez na.rm = TRUE dans les calculs
✅ Utilisez des noms de variables significatifs (net_vat, pas x1)
✅ Commentez votre code pour que les autres le comprennent
✅ Sauvegardez les jeux de données transformés dans le dossier Clean pour les modules futurs
✅ Ajoutez .groups = "drop" après group_by() + summarize()
Note
Prochaines étapes :
Comment Fonctionne l’Affectation
L’opérateur d’affectation
<-stocke les résultats dans un objet :Vous pouvez aussi écraser l’original :
Avertissement
Écraser est permanent ! Si vous n’êtes pas sûr, créez un nouvel objet à la place.