在函数内部使用purrr::pmap
我有兴趣在函数中使用 purrr::pmap()。我在将数据变量名从 我的函数 传递给pmap() 使用的匿名函数时遇到了困难。
library("purrr")
library("dplyr")
# Example data
df = tribble(
~x, ~y, ~z,
1, 5, "A",
4, 6, "B")
df
# Sum of x and y (outside function)
pmap(df, \(x, y, ...) x + y)
#> [[1]]
#> [1] 6
#>
#> [[2]]
#> [1] 10
# Naively wrap that in a function - doesn't work
add_cols = function(dat, a, b){
pmap(dat, \(first = a, second = b, ...) first + second)
}
add_cols(dat = df, a = x, b = y)
#> Error in `pmap()`:
#> ℹ In index: 1.
#> Caused by error:
#> ! object 'x' not found
当我之前尝试类似的事情时,我曾使用来自rlang包的 {{ }} 来注入数据变量名,但我无法在 pmap() 中让它起作用。
# Example where inject works within mutate
add_cols2 = function(dat, a, b){
dat |>
mutate(sum = {{a}} + {{b}})
}
add_cols2(dat = df, a = x, b = y)
#> # A tibble: 2 × 4
#> x y z sum
#> <dbl> <dbl> <chr> <dbl>
#> 1 1 5 A 6
#> 2 4 6 B 10
# But this approach does not work within pmap
add_cols3 = function(dat, a, b){
pmap(dat, \(first = {{a}}, second = {{b}}, ...) first + second)
}
add_cols3(dat = df, a = x, b = y)
#> Error in `pmap()`:
#> ℹ In index: 1.
#> Caused by error:
#> ! object 'x' not found
我的问题是如何将未带引号的数据变量名传递给pmap() 内的匿名函数。
对于这个简单的例子,除了使用pmap之外还有更好的方法(尤其是使用mutate),但我想了解如何实现这一点,并且我的实际问题需要 pmap()。我也知道一些变通方法,包括在add_cols函数中在pmap() 之前重命名变量或创建一个新的数据对象(列表或df),但如果可能的话,我想直接知道如何执行这个操作。
# An example work-around
add_cols4 = function(dat, a, b){
dat = dat |>
rename(c(first = {{a}}, second = {{b}}))
pmap(dat, \(first, second, ...) first + second)
}
add_cols4(dat = df, a = x, b = y)
#> [[1]]
#> [1] 6
#>
#> [[2]]
#> [1] 10
解决方案
我们可以这样做:
add_cols = function(dat, a, b){
purrr::pmap(
unname(as.list(select(dat, {{a}}, {{b}}))),
\(first, second) first + second
)
}
add_cols(dat = df, a = x, b = y)
# [[1]]
# [1] 6
# [[2]]
# [1] 10
我在 select 里进行准引号,因为需要减少传递到 pmap 的列数。并且由于这些列有名称,内部函数里会有一些混乱,因此需要使用 unname(as.list(..))。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。