使用purrr :: pmap使用.f列表名称

时间:2018-07-01 11:14:55

标签: r purrr

以下工作正常:

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

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

2 个答案:

答案 0 :(得分:5)

公式参数~ 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参数访问命名参数。

当名称可用时,将命名函数的参数,如doc所指出的那样。

这说明了pmap(named_list, function(x,y,z) x+y+z)会因错误而失败的原因:

  

未使用的参数(一个= .l [[c(1,i)]],两个= .l [[c(2,i)]],三个= .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

pryrpryr::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)

因此,这不是通用方法,您应该仅在简单情况下使用它。第二种方法虽然有点破绽,但却很普遍。

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

答案 1 :(得分:3)

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