利用 purrr::pmap 的 .f 列表名称

Harnessing .f list names with purrr::pmap

以下工作正常:

pmap_dbl(iris, ~ ..1 + ..2 + ..3 + ..4)

.l 的文档提供 A list of lists. ... List names will be used if present.。这表明您应该能够使用列表名称(即列名称)。然而:

pmap_dbl(iris, ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width)
Error in .f(Sepal.Length = .l[[c(1L, i)]], Sepal.Width = .l[[c(2L, i)]],  : 
  object 'Sepal.Length' not found

如何在实践中利用列表名称?

library(purrr)
named_list <- list(one = c(1, 1),
                   two = c(2, 2),
                   three = c(3, 3))

pmap(named_list, function(one, two, three) one + two + three)

甚至在 pmap 文档中:

# Matching arguments by name
l <- list(a = x, b = y, c = z)
pmap(l, function(c, b, a) a / (b + c))

之所以可行,是因为它希望清楚地看到每个命名元素。

pmap_dbl(iris, function(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species) Sepal.Length + Sepal.Width)

你也可以利用 ... 似乎:

pmap_dbl(iris, function(Sepal.Length, Sepal.Width, ...) Sepal.Length + Sepal.Width)

理想情况下,此示例在实践中只使用 rowSums

公式参数 ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width 传递给 purrr::as_mapper

purrr::as_mapper(~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width)
# function (..., .x = ..1, .y = ..2, . = ..1) 
# Sepal.Length + Sepal.Width + Petal.Length + Petal.Width

你可以看到这个函数没有直接的方法知道这些变量是什么。

我可以想到 3 种解决方法。我将使用@zacdav 的示例,因为它比您的示例更紧凑、更易读:

named_list <- list(one = c(1, 1),
                   two = c(2, 2),
                   three = c(3, 3))

显式定义

您可以明确定义这些变量,如@zacdav 的回答所示。


探索点参数

有一种方法可以通过 as_mapper 返回的函数的 ... 参数访问命名参数。

函数的参数在名称可用时命名,换言之,如文档所述。

这解释了为什么 pmap(named_list, function(x,y,z) x+y+z) 会失败并出现错误:

unused arguments (one = .l[[c(1, i)]], two = .l[[c(2, i)]], three = .l[[c(3, i)]])

参见:

pmap(named_list, ~names(list(...)))
# [[1]]
# [1] "one"   "two"   "three"
# 
# [[2]]
# [1] "one"   "two"   "three"

pmap(unname(named_list), function(x,y,z) x+y+z) 另一方面可以正常工作)

所以这会起作用:

pmap(named_list, ~ with(list(...), one + two + three))
# [[1]]
# [1] 6
# 
# [[2]]
# [1] 6 

使用pryr::f

pryr 为函数定义提供了一个简洁的快捷方式 pryr::f :

library(pryr)
f(one + two + three)
# function (one, three, two) 
# one + two + three

pmap(named_list, f(one + two + three))
# [[1]]
# [1] 6
# 
# [[2]]
# [1] 6
# 

但是在使用它时要小心,全局变量仍将显示为参数,函数是否包含在参数中取决于它们的调用方式。例如:

x <- 1
test <- mean
f(test(x) + lapply(iris,test2))
# function (iris, test2, x) 
# test(x) + lapply(iris, test2)

所以这不是一个通用的方法,您应该只在简单的情况下使用它。第二种方法,虽然有点 hack,但将是通用的。

此外 f 是按字母顺序排列参数,这在处理命名列表时应该不是问题,但在处理部分命名列表时要小心。