【问题标题】:use invoke_map to pass variable names as args使用 invoke_map 将变量名作为参数传递
【发布时间】:2017-09-19 13:48:46
【问题描述】:

我想使用invoke_map 来调用函数列表。我有一组变量名,我想将它们用作每个函数的参数。最终变量名将与group_by 一起使用。

这是一个例子:

library(dplyr)
library(purrr)
first_fun <- function(...){
  by_group = quos(...)
  mtcars %>%
    group_by(!!!by_group) %>%
    count()
}

second_fun <- function(...){
  by_group = quos(...)
  mtcars %>%
    group_by(!!!by_group) %>%
    summarise(avg_wt = mean(wt))
}

first_fun(mpg, cyl) # works
second_fun(mpg, cyl) # works

both_funs <- list(first_fun, second_fun)

both_funs %>%
  invoke_map(mpg, cyl) # What do I do here?

我尝试了各种尝试将变量名放在引号中,enquo 他们,使用vars,引用.data$mpg,等等,但我有点在黑暗中刺伤。

【问题讨论】:

  • This question 展示了如何通过更改函数以从命名参数而不是点获取分组列来解决问题,这是部分解决方案。我仍然对如何使用调用通过点传递变量名的问题感兴趣,尽管答案可能是不要从点中获取变量名。
  • 您可能认为.env 参数在这里可能有用,但invoke_map(first_fun, list(list(mpg, cyl)), .env = as.environment(mtcars)) 也不起作用。

标签: r dplyr purrr


【解决方案1】:

问题不在于您使用的是点,而在于您使用的是名称,并且当调用 map2_impl 时,这些参数会被评估。

试试这个并探索环境:

debugonce(map2)
both_funs %>% invoke_map("mpg", "cyl")

另一方面,这是可行的:

first_fun2 <- function(...){
  mtcars %>%
  {do.call(group_by_,list(.,unlist(list(...))))} %>%
    count()
}

second_fun2 <- function(...){
  mtcars %>%
  {do.call(group_by_,list(.,unlist(list(...))))} %>%
    summarise(avg_wt = mean(wt))
}

both_funs2 <- list(first_fun2, second_fun2)
both_funs2 %>% invoke_map("mpg", "cyl") 

# [[1]]
# # A tibble: 25 x 2
# # Groups:   mpg [25]
# mpg     n
# <dbl> <int>
#   1  10.4     2
# 2  13.3     1
# 3  14.3     1
# 4  14.7     1
# 5  15.0     1
# 6  15.2     2
# 7  15.5     1
# 8  15.8     1
# 9  16.4     1
# 10  17.3     1
# # ... with 15 more rows
# 
# [[2]]
# # A tibble: 25 x 2
# mpg avg_wt
# <dbl>  <dbl>
#   1  10.4 5.3370
# 2  13.3 3.8400
# 3  14.3 3.5700
# 4  14.7 5.3450
# 5  15.0 3.5700
# 6  15.2 3.6075
# 7  15.5 3.5200
# 8  15.8 3.1700
# 9  16.4 4.0700
# 10  17.3 3.7300
# # ... with 15 more rows

【讨论】:

  • 如果问题是正在评估名称,我是否应该能够使用 enquo 系列函数之一来延迟评估?
  • 但是您不只是想延迟评估,您根本不想评估。崩溃的行是 .Call(map2_impl, environment(), ".x", ".y", ".f", "list") 。据我了解,它调用 C 代码并将评估枚举字符串的参数,我认为您的命名参数没有空间通过它。
  • 我还看到了一个概念问题,这些命名变量不引用当前对象中的现有对象或列,在此示例中它们实际上应该是字符串。
  • 这行得通:first_fun3 &lt;- function(vars){ mtcars %&gt;% group_by_at(.vars = vars) %&gt;% count()} 然后用vars=(mpg, cyl) 调用invoke_map 或者如果我可以在评论中正确地格式化。所以也许预期的方法是使用group_by_at 而不是group_by
猜你喜欢
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 2018-02-17
相关资源
最近更新 更多