furrr: operaciones paralelas de purrr
Reemplace map() directamente por future_map() para paralelizar al instante.
furrr: operaciones paralelas de purrr es una lección gratuita de R Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de R Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de R Academy incluye 4 lecciones en total.
furrr: purrr en paralelo
furrr (future + purrr) proporciona reemplazos paralelos directos para todas las funciones purrr::map_*(). Solo tiene que cambiar map() por future_map() después de establecer un plan() para que la canalización se ejecute en paralelo sin modificar su estructura.
library(furrr)
library(future)
# Set up parallel workers
plan(multisession, workers = 4)
# Sequential (purrr)
# result <- purrr::map(1:8, ~.x^2)
# Parallel (furrr) — identical API
result <- future_map(1:8, ~.x^2)
cat(unlist(result), '\n') # 1 4 9 16 25 36 49 64
plan(sequential)plan(multisession, workers = 4)
Especificar workers explícitamente en plan() limita el número de sesiones paralelas de R. Para tareas limitadas por la CPU, workers = parallel::detectCores() - 1 es una convención habitual que deja un núcleo libre para el sistema operativo.
library(furrr)
library(future)
library(parallel)
# Explicit worker count
n_workers <- max(1, detectCores() - 1)
plan(multisession, workers = n_workers)
cat('Active workers:', nbrOfWorkers(), '\n')
cat('Strategy:', class(plan())[1], '\n')
# Run a simple parallel task
results <- future_map_dbl(1:8, ~sqrt(.x))
cat(round(results, 3), '\n')
plan(sequential)future_map_dbl y variantes tipadas
Al igual que purrr, furrr proporciona variantes tipadas: future_map_dbl(), future_map_int(), future_map_chr() y future_map_lgl(). Estas imponen el tipo de retorno y devuelven un vector atómico en lugar de una lista.
library(furrr)
plan(multisession, workers = 2)
# Returns a numeric vector
square_roots <- future_map_dbl(1:6, ~sqrt(.x))
cat('dbl:', round(square_roots, 3), '\n')
# Returns an integer vector
counts <- future_map_int(list('hello', 'world', 'R'), nchar)
cat('int:', counts, '\n')
# Returns a character vector
formatted <- future_map_chr(c(1.23, 4.56, 7.89), ~sprintf('%.1f', .x))
cat('chr:', formatted, '\n')
# Returns a logical vector
positive <- future_map_lgl(-3:3, ~.x > 0)
cat('lgl:', positive, '\n')
plan(sequential)future_map2: Mapeo de dos entradas
future_map2(.x, .y, .f) itera en paralelo sobre dos listas o vectores y pasa los pares correspondientes a la función. Es el equivalente paralelo de purrr::map2().
library(furrr)
plan(multisession, workers = 2)
# Simulate different sample sizes and means
sizes <- c(100, 200, 300, 400)
means <- c(0, 5, -3, 10)
# future_map2 passes each (n, mu) pair to rnorm
samples <- future_map2(sizes, means, ~rnorm(.x, mean = .y))
# Verify: each element has the expected length and approximate mean
for (i in seq_along(samples)) {
cat('n=', sizes[i], 'target_mean=', means[i],
'observed_mean=', round(mean(samples[[i]]), 2), '\n')
}
plan(sequential)furrr_options: Control del comportamiento
furrr_options() se pasa como argumento .options a cualquier llamada a future_map_*(). La configuración más importante es seed = TRUE, que activa el generador de números aleatorios paralelo L'Ecuyer-CMRG para obtener números reproducibles entre los workers.
library(furrr)
plan(multisession, workers = 2)
# Without seed: results differ each run
r1 <- future_map_dbl(1:4, ~rnorm(1))
r2 <- future_map_dbl(1:4, ~rnorm(1))
cat('Without seed - same?', identical(r1, r2), '\n')
# With seed: reproducible
opts <- furrr_options(seed = 42L)
r3 <- future_map_dbl(1:4, ~rnorm(1), .options = opts)
r4 <- future_map_dbl(1:4, ~rnorm(1), .options = opts)
cat('With seed - same?', identical(r3, r4), '\n')
cat('r3:', round(r3, 4), '\n')
plan(sequential)Informes de progreso con progressr
El paquete progressr se integra con furrr para mostrar barras de progreso durante la ejecución paralela. Envuelva el código en with_progress() y cree un progressor() dentro de la función de mapeo.
library(furrr)
library(progressr)
plan(multisession, workers = 2)
# Enable progress reporting
handlers(global = TRUE) # show progress in console
with_progress({
p <- progressor(steps = 8)
results <- future_map(1:8, function(i) {
p() # increment the progress bar
Sys.sleep(0.1)
i^2
})
})
cat('Results:', unlist(results), '\n')
plan(sequential)Variables globales en furrr
Al igual que el paquete future, furrr detecta automáticamente las variables globales a las que se hace referencia dentro de .f. Puede anular este comportamiento con furrr_options(globals = c('var1', 'var2')) para especificar exactamente qué variables globales enviar y reducir la sobrecarga en entornos grandes.
library(furrr)
plan(multisession, workers = 2)
# Global variables auto-detected
scale_factor <- 10
offset <- 5
result <- future_map_dbl(
1:6,
function(x) x * scale_factor + offset
)
cat(result, '\n') # 15 25 35 45 55 65
# Explicit globals control
opts <- furrr_options(
globals = c('scale_factor', 'offset'),
seed = FALSE
)
result2 <- future_map_dbl(
1:6,
function(x) x * scale_factor + offset,
.options = opts
)
cat('Manual globals:', result2, '\n')
plan(sequential)future_pmap: Mapeo de varios argumentos
future_pmap(.l, .f) es la versión paralela de purrr::pmap(). Acepta una lista de vectores o listas y pasa las filas correspondientes como argumentos con nombre, lo que permite realizar cálculos en paralelo con múltiples combinaciones de parámetros.
library(furrr)
plan(multisession, workers = 2)
# Parameter grid
params <- list(
n = c(50, 100, 150, 200),
mean = c(0, 1, 2, 3),
sd = c(1, 2, 1, 0.5)
)
# future_pmap passes each row as arguments to rnorm
samples <- future_pmap(params, function(n, mean, sd) {
x <- rnorm(n, mean = mean, sd = sd)
c(obs_mean = round(mean(x), 3), obs_sd = round(sd(x), 3))
})
for (i in seq_along(samples)) {
cat('n=', params$n[i], ':', samples[[i]], '\n')
}
plan(sequential)Comparación de rendimiento entre furrr y purrr
Los beneficios del paralelismo aumentan con el peso de las tareas. En operaciones triviales como x^2, predomina la sobrecarga y la ejecución secuencial es más rápida. En tareas pesadas, como ajustar muchos modelos, el paralelismo ahorra una cantidad considerable de tiempo.
library(furrr)
library(purrr)
plan(multisession, workers = 4)
# Heavy task: bootstrap a linear model 100 times
heavy <- function(i) {
n <- 200
df <- data.frame(x = rnorm(n), y = rnorm(n))
coef(lm(y ~ x, data = df))[['x']]
}
seq_time <- system.time(map_dbl(1:40, heavy))[['elapsed']]
par_time <- system.time(
future_map_dbl(1:40, heavy, .options = furrr_options(seed = TRUE))
)[['elapsed']]
cat('Sequential:', round(seq_time, 2), 's\n')
cat('Parallel: ', round(par_time, 2), 's\n')
cat('Speedup: ', round(seq_time / max(par_time, 0.001), 2), 'x\n')
plan(sequential)Gestión de errores en future_map
Si el cálculo de cualquier elemento produce un error, future_map() se detiene y vuelve a lanzarlo. Para continuar a pesar de los errores, use los envoltorios purrr::safely() o purrr::possibly() alrededor de su función.
library(furrr)
library(purrr)
plan(multisession, workers = 2)
# Wrap with safely() to capture errors as results
safe_log <- safely(log, otherwise = NA_real_)
inputs <- list(10, -1, 100, 'text', 0.5)
results <- future_map(inputs, safe_log)
for (i in seq_along(results)) {
if (is.null(results[[i]]$error)) {
cat('Input', i, '-> result:', round(results[[i]]$result, 4), '\n')
} else {
cat('Input', i, '-> error:', conditionMessage(results[[i]]$error), '\n')
}
}
plan(sequential)Canalización práctica con furrr
Esta es una canalización completa de principio a fin: cargar datos, ajustar varios modelos en paralelo con semillas reproducibles, extraer métricas de rendimiento y seleccionar el mejor modelo, todo ello mediante el enfoque de furrr.
library(furrr)
library(purrr)
plan(multisession, workers = 4)
set.seed(1)
n <- 300
df <- data.frame(
x1 = rnorm(n), x2 = rnorm(n), x3 = rnorm(n),
y = rnorm(n)
)
formulas <- list(
y ~ x1,
y ~ x1 + x2,
y ~ x1 + x2 + x3,
y ~ x1 * x2
)
# Fit all models in parallel
models <- future_map(
formulas,
~lm(.x, data = df),
.options = furrr_options(seed = FALSE)
)
# Extract adjusted R-squared
adj_r2 <- map_dbl(models, ~summary(.x)$adj.r.squared)
cat('Adjusted R2 per model:',
paste(round(adj_r2, 4), collapse = ', '), '\n')
cat('Best model:', which.max(adj_r2), '\n')
plan(sequential)Comprobación rápida
Desea obtener números aleatorios reproducibles en distintas llamadas paralelas a future_map(). ¿Qué configuración de furrr_options() lo permite?
Resumen: paquete furrr
Ideas clave:
furrres un reemplazo paralelo directo depurrr; solo tiene que cambiarmapporfuture_map- Establezca primero un backend con
plan(multisession, workers = n) - Variantes tipadas:
future_map_dbl(),future_map_int()yfuture_map_chr() - Use
future_map2()yfuture_pmap()para el mapeo paralelo con varias entradas - Use
furrr_options(seed = 42L)para obtener números aleatorios paralelos reproducibles - Integre
progressrpara mostrar barras de progreso durante trabajos paralelos largos - Use
purrr::safely()dentro defuture_map()para crear canalizaciones resistentes a errores
library(furrr)
plan(multisession, workers = 2)
results <- future_map_dbl(
1:6,
~.x^2 + sqrt(.x),
.options = furrr_options(seed = TRUE)
)
cat(round(results, 3), '\n')
plan(sequential)Aprende R con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 43
- Lecciones
- 159
Preguntas frecuentes
¿La lección «furrr: operaciones paralelas de purrr» es gratis?
Sí — el texto completo de «furrr: operaciones paralelas de purrr» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de R Academy, actualiza a CoddyKit PRO. El curso de R Academy incluye 4 lecciones en total.
¿Qué aprenderé en «furrr: operaciones paralelas de purrr»?
Reemplace map() directamente por future_map() para paralelizar al instante. Practicas R Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar R Academy?
No se requiere experiencia previa. R Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «furrr: operaciones paralelas de purrr»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de R Academy?
Sí. Cada lección de R Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Paquete parallel y detectCores()
- El framework future
- furrr: operaciones paralelas de purrr
- Depuración y equilibrio de carga del código paralelo