非循环前置管道场景下purrr替代Map的实现方法咨询
Great question! I totally get where you're coming from—Map's flexibility for scenarios where you have a fixed object paired with multiple iterable lists is really intuitive, and pmap can feel clunky at first if you're trying to shoehorn the fixed object into the iterable list. Let's break down how to replicate (and even improve on) that Map workflow with purrr, using mtcars as an example.
Example Setup
First, let's define a concrete scenario: we'll use mtcars as our fixed data object, plus two iterable lists—one with column names, and another with summary functions we want to apply to those columns.
library(purrr) # Fixed data object dat <- mtcars # Iterable parameters: column names and corresponding functions cols <- c("mpg", "hp", "wt") funs <- list(mean, median, max)
1. Using map2 (for 2 iterable lists + fixed object)
If you have exactly two iterable lists (like cols and funs here), map2 is the cleanest purrr equivalent. Unlike Map, you don't need to replicate the fixed object into a matching-length list—just reference it directly in the lambda function:
purrr map2 Solution
map2(cols, funs, ~ .y(dat[[.x]])) # Output: # [[1]] # [1] 20.09062 # # [[2]] # [1] 123 # # [[3]] # [1] 5.424
Equivalent Map Code
For comparison, here's how you'd do this with Map—notice you have to wrap dat in rep(list(...)) to match the length of the iterable lists:
Map(function(d, c, f) f(d[[c]]), rep(list(dat), length(cols)), cols, funs)
2. Using pmap (for 3+ iterable lists + fixed object)
When you have three or more iterable lists, pmap is the way to go. Again, no need to replicate the fixed object—just bundle your iterable parameters into a named list, and reference the fixed object inside the function:
Let's add a third iterable parameter (e.g., na.rm flags) to make this concrete:
na.rm_flags <- c(TRUE, FALSE, TRUE)
purrr pmap Solution
pmap( list(col = cols, fn = funs, na.rm = na.rm_flags), function(col, fn, na.rm) fn(dat[[col]], na.rm = na.rm) )
Equivalent Map Code
Once again, Map requires replicating the fixed object to align lengths:
Map(function(d, c, f, nr) f(d[[c]], na.rm = nr), rep(list(dat), length(cols)), cols, funs, na.rm_flags)
Key Takeaway
The main reason pmap felt harder than Map is likely because you were trying to include the fixed object in the iterable list passed to pmap. Instead, leverage purrr's support for referencing variables from the outer environment in lambda functions—this eliminates the need to replicate the fixed object, making the code cleaner and more readable than the equivalent Map code.
内容的提问来源于stack exchange,提问作者Tyler Rinker

