R Academy · Lekcja

reduce(), accumulate() i walk()

Redukuj listy, twórz wyniki skumulowane i stosuj efekty uboczne za pomocą walk().

Lekcja 3 z 413 kroki

reduce(), accumulate() i walk() to bezpłatna lekcja R Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.

Poza map() — inne funkcje purrr

Funkcja map() stosuje funkcję niezależnie do każdego elementu, ale niektóre zadania wymagają operacji, które łączą elementy (reduce), gromadzą wyniki pośrednie (accumulate) lub stosują funkcje wyłącznie ze względu na efekty uboczne (walk). purrr udostępnia do każdego z tych zastosowań osobne funkcje.

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() — redukowanie listy do jednej wartości

reduce(.x, .f, .init) kumulacyjnie stosuje .f do elementów .x, od lewej do prawej, redukując listę do pojedynczej wartości. reduce(list(a,b,c), f) oblicza 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() z .init

Argument .init określa wartość początkową (ziarno). Pierwsze wywołanie ma postać f(.init, x[1]). Jest to niezbędne, gdy lista może być pusta (wynikiem redukcji będzie .init) lub gdy wymagany jest konkretny stan początkowy.

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() z ramkami danych — łańcuchowe złączenia

Jednym z najbardziej użytecznych zastosowań reduce() jest łączenie listy ramek danych. Zamiast pisać left_join(left_join(df1, df2), df3), należy użyć 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() — zachowywanie wyników pośrednich

accumulate(.x, .f) działa podobnie jak reduce(), ale zachowuje wszystkie wartości pośrednie. Zwraca wektor (lub listę) o tej samej długości co dane wejściowe, pokazując wynik narastająco po każdym kroku.

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() do uzyskiwania wyników krok po kroku

accumulate() jest szczególnie przydatna do śledzenia kolejnych kroków algorytmu, budowania ciągów znaków znak po znaku oraz wszelkich procesów, w których chcą Państwo analizować każdy stan pośredni, a nie tylko wynik końcowy.

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() — efekty uboczne bez zwracania wyniku

walk(.x, .f) stosuje .f do każdego elementu .x wyłącznie ze względu na efekty uboczne (drukowanie, zapisywanie plików, wysyłanie komunikatów). Funkcja niewidocznie zwraca .x, dzięki czemu można używać jej w potoku bez przerywania łańcucha.

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() w potoku

Ponieważ walk() niewidocznie zwraca .x, można wstawić ją do potoku dplyr, aby rejestrować lub wyświetlać wyniki pośrednie bez przerywania przepływu. Można traktować ją jako punkt podglądu używany do debugowania lub rejestrowania informacji.

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() — efekty uboczne z dwoma danymi wejściowymi

walk2(.x, .y, .f) to wersja walk() przyjmująca dwa dane wejściowe. Klasyczny przypadek użycia to zapisywanie wielu ramek danych do plików, gdzie .x jest listą ramek danych, a .y — listą ścieżek plików.

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() — walk z indeksem

iwalk(.x, .f) działa podobnie jak walk(), ale przekazuje nazwę elementu (lub indeks) jako drugi argument .y. Jest to wygodne, gdy w ramach efektu ubocznego trzeba wiedzieć, który element jest przetwarzany.

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() — redukcja od prawej do lewej

reduce(.x, .f, .dir='backward') (lub wycofana funkcja reduce_right()) stosuje funkcję od prawej do lewej: f(a, f(b, f(c, d))). Ma to znaczenie w przypadku operacji nieprzemiennych, takich jak odejmowanie lub budowanie ciągów znaków.

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

Szybkie sprawdzenie

Kiedy należy użyć walk() zamiast map()?

Podsumowanie: reduce, accumulate, walk

Najważniejsze informacje o reduce, accumulate i walk:

  • reduce(.x, .f) — redukuje listę do jednej wartości (od lewej do prawej); .init ustawia wartość początkową
  • reduce(list_of_dfs, left_join) — użyteczny wzorzec do łańcuchowego wykonywania złączeń
  • accumulate(.x, .f) — działa jak reduce, ale zwraca wszystkie wyniki pośrednie
  • walk(.x, .f) — stosuje funkcję ze względu na efekty uboczne (drukowanie, zapisywanie, rejestrowanie); zwraca .x
  • walk2(.x, .y, .f) — walk z dwoma danymi wejściowymi (np. ramka danych + ścieżka pliku)
  • iwalk(.x, .f) — walk przekazujący nazwę elementu jako drugi 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'))
Bezpłatny start

Ucz się R dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
43
Lekcje
159

Często zadawane pytania

Czy lekcja „reduce(), accumulate() i walk()” jest bezpłatna?

Tak — pełny tekst „reduce(), accumulate() i walk()” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „reduce(), accumulate() i walk()”?

Redukuj listy, twórz wyniki skumulowane i stosuj efekty uboczne za pomocą walk(). Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć R Academy?

Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „reduce(), accumulate() i walk()”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?

Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. map() i warianty typowane
  2. map2() i pmap() dla wielu danych wejściowych
  3. reduce(), accumulate() i walk()
  4. keep(), discard() i filtrowanie list
← Powrót do R Academy