在 R 中:如何将函数名(不是字符)作为参数传递给另一个内部函数而不丢失初始函数名?
In R: how to pass function name (not as character) as an argument to another inner function without loss of initial function name?
我有两个功能:
Worker
that does the job
Boss
that calls the "Worker" and ask it to execute given function called by name
如果我直接调用 Worker
,它会收到函数体及其名称,因此它可以同时使用两者。但是,如果我通过 Boss
调用 Worker
,Boss
会将 Worker
中的函数名称屏蔽为 FUN
require(magrittr)
require(dplyr)
df <- data.frame(one = c(1,1,1), two = c(1,3,NA))
Worker <- function(df, feature, FUN, ...) {
newvarname <- paste0(substitute(FUN), feature)
df %>% mutate(!!newvarname := FUN(!!as.name(feature), ...))
}
Boss <- function(df, feature, FUN, ...) {
df %>% Worker(feature, FUN, ...)
}
Boss(df, "two", mean, na.rm = T)
# one two FUNtwo
# 1 1 1 2
# 2 1 3 2
# 3 1 NA 2
Worker(df, "one", mean)
# one two meanone
# 1 1 1 1
# 2 1 3 1
# 3 1 NA 1
我玩 quote/quo/enquo/substitute/get/match.fun
很累,但没有任何帮助。这是否意味着 R 不能将整个函数对象(名称和主体)作为参数传递?
可以在Boss
里面加上eval(substitute())
,不过好像不太满意
Boss <- function(df, feature, FUN, ...) {
eval(substitute(df %>% Worker(feature, FUN,...)))
}
Boss(df, "two", mean, na.rm = T)
one two meantwo
1 1 1 2
2 1 3 2
3 1 NA 2
这是一种处理方法 rlang
:
library(rlang)
df <- data.frame(one = c(1,1,1), two = c(1,3,NA))
Worker <- function(df, feature, FUN, ...) {
if (!is_quosure(FUN)) {
fun_q <- quo(FUN)
newvarname <- paste0(substitute(FUN), feature)
}
else {
fun_q <- FUN
newvarname <- paste0(quo_text(fun_q), feature)
}
df %>% mutate(!!newvarname := eval(fun_q)(!!as.name(feature), ...))
}
Boss <- function(df, feature, FUN, ...) {
fun_q <- enquo(FUN)
df %>% Worker(feature, fun_q, ...)
}
Boss(df, "two", mean, na.rm = T)
one two meantwo
1 1 1 2
2 1 3 2
3 1 NA 2
Worker(df, "one", mean)
one two meanone
1 1 1 1
2 1 3 1
3 1 NA 1
我有两个功能:
Worker
that does the jobBoss
that calls the "Worker" and ask it to execute given function called by name
如果我直接调用 Worker
,它会收到函数体及其名称,因此它可以同时使用两者。但是,如果我通过 Boss
调用 Worker
,Boss
会将 Worker
中的函数名称屏蔽为 FUN
require(magrittr)
require(dplyr)
df <- data.frame(one = c(1,1,1), two = c(1,3,NA))
Worker <- function(df, feature, FUN, ...) {
newvarname <- paste0(substitute(FUN), feature)
df %>% mutate(!!newvarname := FUN(!!as.name(feature), ...))
}
Boss <- function(df, feature, FUN, ...) {
df %>% Worker(feature, FUN, ...)
}
Boss(df, "two", mean, na.rm = T)
# one two FUNtwo
# 1 1 1 2
# 2 1 3 2
# 3 1 NA 2
Worker(df, "one", mean)
# one two meanone
# 1 1 1 1
# 2 1 3 1
# 3 1 NA 1
我玩 quote/quo/enquo/substitute/get/match.fun
很累,但没有任何帮助。这是否意味着 R 不能将整个函数对象(名称和主体)作为参数传递?
可以在Boss
里面加上eval(substitute())
,不过好像不太满意
Boss <- function(df, feature, FUN, ...) {
eval(substitute(df %>% Worker(feature, FUN,...)))
}
Boss(df, "two", mean, na.rm = T)
one two meantwo
1 1 1 2
2 1 3 2
3 1 NA 2
这是一种处理方法 rlang
:
library(rlang)
df <- data.frame(one = c(1,1,1), two = c(1,3,NA))
Worker <- function(df, feature, FUN, ...) {
if (!is_quosure(FUN)) {
fun_q <- quo(FUN)
newvarname <- paste0(substitute(FUN), feature)
}
else {
fun_q <- FUN
newvarname <- paste0(quo_text(fun_q), feature)
}
df %>% mutate(!!newvarname := eval(fun_q)(!!as.name(feature), ...))
}
Boss <- function(df, feature, FUN, ...) {
fun_q <- enquo(FUN)
df %>% Worker(feature, fun_q, ...)
}
Boss(df, "two", mean, na.rm = T)
one two meantwo
1 1 1 2
2 1 3 2
3 1 NA 2
Worker(df, "one", mean)
one two meanone
1 1 1 1
2 1 3 1
3 1 NA 1