reduce(), accumulate() et walk()
Réduisez des listes, construisez des résultats cumulés et appliquez des effets secondaires avec walk().
reduce(), accumulate() et walk() est une leçon R Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage R Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours R Academy comprend 4 leçons au total.
Au-delà de map() — Autres fonctions de purrr
Alors que map() applique une fonction indépendamment à chaque élément, certaines tâches nécessitent de combiner les éléments (reduce), d’accumuler les résultats intermédiaires ou d’appliquer des fonctions uniquement pour leurs effets de bord (walk). purrr fournit des fonctions dédiées à chacun de ces cas.
library(purrr)
# Example: combining a list of numbers into a single value
nums <- list(1, 2, 3, 4, 5)
# We want: 1 + 2 + 3 + 4 + 5 = 15
# map() can't do this — it returns 5 separate results
# reduce() folds the list into one value
result <- reduce(nums, `+`)
cat('Sum via reduce:', result)reduce() — Réduire une liste à une valeur
reduce(.x, .f, .init) applique cumulativement .f aux éléments de .x, de gauche à droite, afin de réduire la liste à une seule valeur. reduce(list(a,b,c), f) calcule f(f(a,b),c).
library(purrr)
# reduce with max: find the overall maximum
values <- list(42, 17, 89, 55, 23)
result <- reduce(values, max)
cat('Maximum:', result, '\n')
# reduce with paste: concatenate strings
words <- list('The', 'quick', 'brown', 'fox')
reduce(words, paste)reduce() avec .init
L’argument .init fournit une valeur de départ (seed). Le premier appel devient f(.init, x[1]). Cela est essentiel lorsque la liste peut être vide (la réduction renvoie alors .init) ou lorsque vous avez besoin d’un état initial précis.
library(purrr)
# Running count of elements matching a condition
data <- list(5, 12, 3, 18, 7, 15, 2)
# Count values greater than 10, starting from 0
reduce(data, function(count, x) count + (x > 10), .init = 0L)
# Also useful for string building:
reduce(c('A','B','C'), paste, sep='-', .init='START')reduce() avec des cadres de données — Chaîner des jointures
L’une des utilisations les plus puissantes de reduce() consiste à joindre une liste de cadres de données. Au lieu d’écrire left_join(left_join(df1, df2), df3), utilisez reduce(list_of_dfs, left_join, by='key').
library(purrr)
library(dplyr)
base_df <- data.frame(id=1:3, name=c('Alice','Bob','Carol'))
scores <- data.frame(id=1:3, score=c(85,90,78))
grades <- data.frame(id=1:3, grade=c('B','A','C'))
city <- data.frame(id=1:3, city=c('NYC','LA','Chicago'))
dfs <- list(base_df, scores, grades, city)
reduce(dfs, left_join, by='id')accumulate() — Conserver les résultats intermédiaires
accumulate(.x, .f) fonctionne comme reduce(), mais conserve toutes les valeurs intermédiaires. La fonction renvoie un vecteur (ou une liste) de même longueur que l’entrée, montrant le résultat cumulé après chaque étape.
library(purrr)
# Running sum — same as cumsum() but via accumulate
values <- c(100, 120, 95, 140, 160)
accumulate(values, `+`)
# Running maximum
accumulate(c(50, 52, 48, 55, 53, 58), max)accumulate() pour des résultats étape par étape
accumulate() est particulièrement utile pour suivre les étapes d’un algorithme, construire des chaînes de caractères caractère par caractère ou gérer tout processus dans lequel vous souhaitez examiner chaque état intermédiaire, et pas seulement le résultat final.
library(purrr)
# Compound interest step by step
principal <- 1000
rates <- c(0.05, 0.05, 0.05, 0.05, 0.05) # 5% per year
accumulate(rates, function(balance, rate) {
round(balance * (1 + rate), 2)
}, .init = principal)walk() — Effets de bord sans valeur de retour
walk(.x, .f) applique .f à chaque élément de .x uniquement pour ses effets de bord (afficher, écrire des fichiers, envoyer des messages). La fonction renvoie .x de manière invisible, ce qui permet de l’utiliser dans un pipeline sans interrompre la chaîne.
library(purrr)
# Print a summary for each dataset
datasets <- list(
mtcars = mtcars[,1:3],
iris = iris[,1:3]
)
walk(datasets, function(df) {
cat('Rows:', nrow(df), '| Cols:', ncol(df),
'| NAs:', sum(is.na(df)), '\n')
})walk() dans un pipeline
Comme walk() renvoie .x de manière invisible, vous pouvez l’insérer dans un pipeline dplyr pour journaliser ou afficher des résultats intermédiaires sans interrompre le flux. Considérez-la comme un point d’observation pour le débogage ou la journalisation.
library(purrr)
library(dplyr)
results <- list(
East = data.frame(rep=c('A','B'), sales=c(100,120)),
West = data.frame(rep=c('C','D'), sales=c(200,190))
)
# Log each region's data, then continue processing
region_totals <- results %>%
walk(~cat('Processing:', nrow(.x), 'rows\n')) %>%
map_dbl(~sum(.x$sales))
print(region_totals)walk2() — Effets de bord avec deux entrées
walk2(.x, .y, .f) est la version à deux entrées de walk(). Un cas d’utilisation classique consiste à écrire plusieurs cadres de données dans des fichiers, où .x est la liste des cadres de données et .y la liste des chemins de fichiers.
library(purrr)
data_list <- list(
east = data.frame(x=1:3, y=4:6),
west = data.frame(x=7:9, y=10:12)
)
file_paths <- list(
'/tmp/east_data.csv',
'/tmp/west_data.csv'
)
# Write each data frame to its corresponding path
walk2(data_list, file_paths, function(df, path) {
write.csv(df, path, row.names=FALSE)
cat('Written:', path, '\n')
})iwalk() — Parcourir avec un indice
iwalk(.x, .f) fonctionne comme walk(), mais transmet le nom de l’élément (ou son indice) comme deuxième argument .y. C’est pratique lorsque vous devez savoir quel élément vous traitez dans le cadre de l’effet de bord.
library(purrr)
region_counts <- list(East=150, West=200, North=85, South=120)
# Print each region with its rank
iwalk(region_counts, function(count, name) {
cat(name, ':', count, 'customers\n')
})reduce_right() — Réduction de droite à gauche
reduce(.x, .f, .dir='backward') (ou reduce_right(), désormais obsolète) applique la fonction de droite à gauche : f(a, f(b, f(c, d))). Cela est important pour les opérations non commutatives, comme la soustraction ou la construction de chaînes de caractères.
library(purrr)
words <- c('fox','brown','quick','The')
# Left-to-right: 'The quick brown fox'
reduce(rev(words), paste)
# Right-to-left: same effect but starting from right
reduce(words, function(a, b) paste(b, a))Vérification rapide
Quand utiliseriez-vous walk() plutôt que map() ?
Récapitulatif : reduce, accumulate, walk
Points essentiels concernant reduce, accumulate et walk :
reduce(.x, .f)— réduit une liste à une valeur, de gauche à droite ;.initdéfinit la valeur de départreduce(list_of_dfs, left_join)— schéma puissant pour chaîner des jointuresaccumulate(.x, .f)— fonctionne comme reduce, mais renvoie tous les résultats intermédiaireswalk(.x, .f)— applique une fonction pour ses effets de bord (afficher, écrire, journaliser) ; renvoie.xwalk2(.x, .y, .f)— walk avec deux entrées (par exemple, un cadre de données et un chemin de fichier)iwalk(.x, .f)— walk utilisant le nom de l’élément comme deuxième argument
library(purrr)
library(dplyr)
# reduce() joins a list of data frames, accumulate() shows interim states
monthly_sums <- c(100, 120, 95, 140, 160, 130)
cat('reduce (total): ', reduce(monthly_sums, `+`), '\n')
cat('accumulate (running):', accumulate(monthly_sums, `+`), '\n')
# walk() for side-effect logging
results <- list(a=42, b=17, c=89)
walk(results, ~cat('Value:', .x, '\n'))Questions Fréquemment Posées
La leçon « reduce(), accumulate() et walk() » est-elle gratuite ?
Oui — le texte complet de « reduce(), accumulate() et walk() » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours R Academy, passe à CoddyKit PRO. Le cours R Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « reduce(), accumulate() et walk() » ?
Réduisez des listes, construisez des résultats cumulés et appliquez des effets secondaires avec walk(). Tu pratiques R Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer R Academy ?
Aucune expérience préalable n'est requise. R Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « reduce(), accumulate() et walk() » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon R Academy ?
Oui. Chaque leçon R Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- map() et ses variantes typées
- map2() et pmap() pour plusieurs entrées
- reduce(), accumulate() et walk()
- keep(), discard() et filtrage de listes