使用*apply或purrr进行函数式编程是我的主要工作,但我不明白pmap如何处理函数参数。
H 215H 116而IE 117不能E 218使用完全不同的名称。H 219G 220我一直在研究多个类似的问题,但没有找到合适的答案
( A)发生了什么
( B)如何使用任意函数参数名称?
# dummy data -----------------------------------------------------------------
(iter_tibble <- tibble::tibble(a = 1:2,
b = 3:4,
c = 7:6))
#> # A tibble: 2 x 3
#> a b c
#> <int> <int> <int>
#> 1 1 3 7
#> 2 2 4 6
# pmap it --------------------------------------------------------------------
# standard way
purrr::pmap(iter_tibble, function(a, b, c) {
paste(a, b, c)
})
#> [[1]]
#> [1] "1 3 7"
#>
#> [[2]]
#> [1] "2 4 6"
# switch order
# works and a maps to a, b to b etc
purrr::pmap(iter_tibble, function(b, c, a) {
paste(a, b, c)
})
#> [[1]]
#> [1] "1 3 7"
#>
#> [[2]]
#> [1] "2 4 6"
# name arguments
purrr::pmap(iter_tibble, function(a1 = a, b1 = b, c1 = c) {
paste(a1, b1, c1)
})
#> [[1]]
#> [1] "1 3 7"
#>
#> [[2]]
#> [1] "2 4 6"
# name arguments and switch order
purrr::pmap(iter_tibble, function(b1 = b, c1 = c, asterix = a) {
paste(b1, asterix, c1)
})
#> [[1]]
#> [1] "3 1 7"
#>
#> [[2]]
#> [1] "4 2 6"
# but when using a different initial letter
# ERROR
purrr::pmap(iter_tibble,
purrr::safely(
function(b1 = b, c1 = c, obelix = a) {
paste(b1, obelix, c1)
}
))[1]
#> [[1]]
#> [[1]]$result
#> NULL
#>
#> [[1]]$error
#> <simpleError in .f(...): unused argument (a = 1)>这种行为与在常规R函数中调用参数是完全不同的,在这种情况下,缩略语是可能的(但实践却很糟糕),但扩展是不可能的。
# regular function usage -----------------------------------------------------
# abbrevate arguments - no problem
sample(1:4, s = 5, repla = TRUE)
#> [1] 1 3 4 3 1
# extend arguments? nope
sample(1:4, size = 5, replaceeeee = TRUE)
#> Error in sample(1:4, size = 5, replaceeeee = TRUE): unused argument (replaceeeee = TRUE)我猜答案是关于C的pmap调用,而不是R中发生的事情。
发布于 2021-03-25 01:44:27
这里的误解是,您的第三和第四个选项没有“命名参数”,而是默认的参数值。您正在向.f参数pmap提供函数定义,而不是函数调用。
pmap的部分参数匹配方式与基R相同。打开options(warnPartialMatchArgs = TRUE)可能会使这一点更加清晰。在这里,我将以您的第三个例子为例,分解函数定义,以便更清楚地了解正在发生的事情:
iter_tibble <- tibble::tibble(
a = 1:2,
b = 3:4,
c = 7:6
)
f3 <- function(a1 = a, b1 = b, c1 = c) {
paste(a1, b1, c1)
}
purrr::pmap(iter_tibble, f3)
#> Warning in .f(a = .l[[1L]][[i]], b = .l[[2L]][[i]], c = .l[[3L]][[i]], ...):
#> partial argument match of 'a' to 'a1'
#> Warning in .f(a = .l[[1L]][[i]], b = .l[[2L]][[i]], c = .l[[3L]][[i]], ...):
#> partial argument match of 'b' to 'b1'
#> Warning in .f(a = .l[[1L]][[i]], b = .l[[2L]][[i]], c = .l[[3L]][[i]], ...):
#> partial argument match of 'c' to 'c1'
#> Warning in .f(a = .l[[1L]][[i]], b = .l[[2L]][[i]], c = .l[[3L]][[i]], ...):
#> partial argument match of 'a' to 'a1'
#> Warning in .f(a = .l[[1L]][[i]], b = .l[[2L]][[i]], c = .l[[3L]][[i]], ...):
#> partial argument match of 'b' to 'b1'
#> Warning in .f(a = .l[[1L]][[i]], b = .l[[2L]][[i]], c = .l[[3L]][[i]], ...):
#> partial argument match of 'c' to 'c1'
#> [[1]]
#> [1] "1 3 7"
#>
#> [[2]]
#> [1] "2 4 6"这与您描述的正则R函数的情况完全相同,其中提供的命名参数可以是函数参数的缩写。换句话说,对于表的第一行,pmap基本上构建了调用f3(a = 1, b = 3, c = 7)。a、b和c来自列名,值来自行。
当试图计算这个调用时,我们看到函数f3没有参数a,但是它有一个参数a1。因此,调用中的命名参数a = 1与函数定义中的a1部分匹配。这就是部分匹配警告在输出中描述的内容。没有“扩展”发生。参数a1的默认值为a这一事实在这里完全无关紧要。
如果您想调用一个函数并将tibble中的值传递给不同命名的参数,请使用它周围的一个包装器来更改接口。您可以使用单独的命名函数或使用~匿名函数语法(非常常见)来实现这一点。使用您的第五个示例:
iter_tibble <- tibble::tibble(
a = 1:2,
b = 3:4,
c = 7:6
)
f5 <- function(b1, obelix, c1) {
paste(b1, obelix, c1)
}
f5_wrapper <- function(a, b, c) {
f5(b1 = b, obelix = a, c1 = c)
}
purrr::pmap(iter_tibble, f5_wrapper)
#> [[1]]
#> [1] "3 1 7"
#>
#> [[2]]
#> [1] "4 2 6"
purrr::pmap(iter_tibble, ~ f5(b1 = ..2, obelix = ..1, c1 = ..3))
#> [[1]]
#> [1] "3 1 7"
#>
#> [[2]]
#> [1] "4 2 6"https://stackoverflow.com/questions/66791203
复制相似问题