Pipeline de préparation de données avec R dplyr : des données brutes aux tables propres
Problème
Les analystes perdent du temps à écrire des boucles R répétitives pour nettoyer les jeux de données. Le résultat : des scripts fragiles, des colonnes incohérentes et des itérations lentes à chaque nouvel arrivage de fichier.
Amplification
Les étapes manuelles s’empilent : sélectionner les mauvaises colonnes, appliquer les transformations dans le mauvais ordre, ou oublier de gérer correctement factor versus character. Chaque erreur oblige à relancer le script et fait courir le risque de diffuser des métriques incorrectes vers les tableaux de bord en aval.
Solution
Adopter un pipeline dplyr cohérent qui reflète la logique SQL et rend chaque transformation lisible. Les verbes ci‑dessous couvrent la sélection de colonnes, le filtrage des lignes, la création de nouvelles variables, les agrégations, le tri, et les jointures sûres afin que les données soient propres avant le modèle ou la visualisation.
Pipeline de base en action
library(dplyr)
clean_sales <- raw_sales %>%
mutate(
region = as.character(region), # avoid accidental factor levels
revenue = price * quantity
) %>%
filter(!is.na(revenue), revenue > 0) %>%
select(order_id, region, revenue, channel, order_date) %>%
arrange(desc(revenue)) %>%
group_by(region, channel) %>%
summarise(
orders = n(),
revenue = sum(revenue),
avg_order = mean(revenue),
.groups = "drop"
)Verbes dplyr et équivalents SQL
| dplyr verb | Purpose | SQL analogy | Quick note |
|---|---|---|---|
select() | keep or rename columns | SELECT col1, col2 | Use everything() to reorder quickly. |
filter() | row subsets | WHERE condition | Combine with %in% for multiple values. |
mutate() | add/transform columns | SELECT col1, col2*2 AS col2x | Prefer if_else() for type-stable logic. |
summarise() + group_by() | grouped metrics | GROUP BY ... | Add .groups = "drop" to ungroup. |
arrange() | ordering rows | ORDER BY | Use desc() for descending. |
left_join() | enrich with lookup | LEFT JOIN | Keep join keys the same type (character vs factor). |
bind_rows() / bind_cols() | stack or widen tables | UNION ALL / column concatenation | Ensure matching schemas when stacking. |
Jointures vs. concaténations en un coup d’œil
# Join: add columns from a lookup table
sales_with_regions <- sales %>%
left_join(region_lookup, by = "region_id")
# Bind: stack identical schemas
all_sales <- bind_rows(sales_2023, sales_2024)Éviter les pièges de facteurs et d’encodage
- Convertir les identifiants en
characteravant les jointures pour éviter des niveaux defactorincompatibles. - Utiliser
mutate(across(where(is.factor), as.character))si un CSV a été lu avec des facteurs implicites. - Standardiser le texte avec
stringr::str_trimettoloweravant le groupement pour éviter les catégories dupliquées.
Modèle de départ rapide
prep_data <- function(df) {
df %>%
mutate(across(where(is.factor), as.character)) %>%
filter(!is.na(key_id)) %>%
distinct() %>%
select(key_id, everything())
}Checklist avant de sauvegarder
- Les colonnes sont explicitement sélectionnées et ordonnées.
- Les jointures clés utilisent des types correspondants et des suffixes explicites si nécessaire (
suffix = c(".src", ".lkp")). - Les résumés suppriment le groupement pour éviter les surprises dans les étapes suivantes.
- Les sorties ne contiennent que des colonnes propres, lisibles par l’humain et prêtes pour les graphiques ou les modèles.
Guides associés
- Construire des tables tidy depuis zéro : Creating Dataframe in R
- Regrouper les données pour les résumés : Grouping in R with group_by()
- Préparer pour la visualisation : R ggplot2 Quickstart