如何在使用 enquo() 的函数上使用 purrr:: invoke_map()?
How can I use purrr:: invoke_map(), on a function that uses enquo()?
抱歉,我知道标题不是最好的。
所以,我正在尝试编写一个函数来检查 2 个函数的输出是否相同。我正在尝试使用 purrr::invoke_map()
执行此操作。但是,我正在努力让它与使用 enquo()
的任何函数一起使用。
我认为问题是因为在我希望对参数求值之前对它们求值。
library(tidyverse)
check_output <- function(function_list, param_list = NULL){
param_list <- list(param_list)
output <- invoke_map(.f = function_list, .x = param_list)
identical(output[1], output[2])
}
check_output(function_list = list(cumprod, cumsum), # This works
param_list = list(x = iris$Sepal.Length))
check_output(function_list = list(cumsum, cumsum), # This works
param_list = list(x = iris$Sepal.Length))
m <- function(data, col_name){ # Enquo test function
col_name <- enquo(col_name)
data %>%
select(!!col_name)
}
n <- m
n(iris, Species) # Seeing if the functions work
check_output(function_list = list(m, n), # The call doesn't work
param_list = list(data = iris, col_name = Species))
我通过添加一个名为 add_quo 的辅助函数解决了我的问题,它将适当的参数转换为 quosures。
require(purrr)
require(magrittr)
require(rlang) # add_quo uses this package
add_quo <- function(...) {
## Formats arguments for use in invoke_map()
# Create a logical vector for use as an index below
index <- exprs(...) %>% # Captures the arguments
unlist() %>% # Makes them mappable
map_if(negate(is.name),
.f = function(x) {return(TRUE)}) %>% # Replaces unnecessary args with TRUE
map_if(is.name, as_character) %>% # Converts named arguments to characters
map_if(is.character, exists) %>% # Replaces named args that aren't objects as FALSE
unlist() # To make index mappable
# Wraps named args that aren't objects in new_quosure()
exprs(...) %>% # Captures arguments
unlist() %>% # Makes them mappable
map_if(!index, new_quosure, # Wraps non-object named arg in new_quosure()
env = global_env()) %>% # new_quosure() used instead of quo() as env must be global
map_if(index, eval) %>% # Removes expr() formatting
list() # Makes arguments usable in invoke_map()
}
is.output.same<- function(.f_list, ...) {
## Checks to see if functions produce identical output
param_list <- add_quo(...) # Enables function with dplyr syntax to work
invoke_map(.f = .f_list, .x = param_list) %>% # Pass args to functions
reduce(identical) # Sees if all outputs are identical
}
check_output(function_list = list(m, n), data = iris, col_name = Species) #now works
抱歉,我知道标题不是最好的。
所以,我正在尝试编写一个函数来检查 2 个函数的输出是否相同。我正在尝试使用 purrr::invoke_map()
执行此操作。但是,我正在努力让它与使用 enquo()
的任何函数一起使用。
我认为问题是因为在我希望对参数求值之前对它们求值。
library(tidyverse)
check_output <- function(function_list, param_list = NULL){
param_list <- list(param_list)
output <- invoke_map(.f = function_list, .x = param_list)
identical(output[1], output[2])
}
check_output(function_list = list(cumprod, cumsum), # This works
param_list = list(x = iris$Sepal.Length))
check_output(function_list = list(cumsum, cumsum), # This works
param_list = list(x = iris$Sepal.Length))
m <- function(data, col_name){ # Enquo test function
col_name <- enquo(col_name)
data %>%
select(!!col_name)
}
n <- m
n(iris, Species) # Seeing if the functions work
check_output(function_list = list(m, n), # The call doesn't work
param_list = list(data = iris, col_name = Species))
我通过添加一个名为 add_quo 的辅助函数解决了我的问题,它将适当的参数转换为 quosures。
require(purrr)
require(magrittr)
require(rlang) # add_quo uses this package
add_quo <- function(...) {
## Formats arguments for use in invoke_map()
# Create a logical vector for use as an index below
index <- exprs(...) %>% # Captures the arguments
unlist() %>% # Makes them mappable
map_if(negate(is.name),
.f = function(x) {return(TRUE)}) %>% # Replaces unnecessary args with TRUE
map_if(is.name, as_character) %>% # Converts named arguments to characters
map_if(is.character, exists) %>% # Replaces named args that aren't objects as FALSE
unlist() # To make index mappable
# Wraps named args that aren't objects in new_quosure()
exprs(...) %>% # Captures arguments
unlist() %>% # Makes them mappable
map_if(!index, new_quosure, # Wraps non-object named arg in new_quosure()
env = global_env()) %>% # new_quosure() used instead of quo() as env must be global
map_if(index, eval) %>% # Removes expr() formatting
list() # Makes arguments usable in invoke_map()
}
is.output.same<- function(.f_list, ...) {
## Checks to see if functions produce identical output
param_list <- add_quo(...) # Enables function with dplyr syntax to work
invoke_map(.f = .f_list, .x = param_list) %>% # Pass args to functions
reduce(identical) # Sees if all outputs are identical
}
check_output(function_list = list(m, n), data = iris, col_name = Species) #now works