使用字符向量动态生成另一个 R 函数的 R 函数
An R function to dynamically generate another R function using a character vector
我正在围绕 rBayesianOptimization
和 caret
R 包编写一个包装函数。下面描述的问题是主包装函数内部步骤的一部分。我需要将特定模型的超参数(这是下面 input
表示的)传递给将在高斯过程模型中采样的函数。超参数当前存储在字符向量中。
有没有办法在 R 中使用字符向量动态生成函数?我需要一个实际上创建另一个函数的函数。例如,
# start with this...
input <- c("a","b")
# ...and an intermediate function generates this
test_function <- function(a=a,b=b) {
d <- data.frame(a=a,b=b)
}
此外,该解决方案需要能够处理各种长度和内容的输入。所以这样的事情也应该有效,
# start with this...
input <- c("c","d","e","f")
# ...and an intermediate function generates this
test_function <- function(c=c,d=d,e=e,f=f) {
d <- data.frame(c=c,d=d,e=e,f=f)
}
这是一个玩具示例,但足以回答我的问题。
这是对您发布的简单示例的简单回答。听起来您的实际工作可能需要更复杂的方法,但这可能会有所帮助。我敢肯定还有其他方法可以更快地做到这一点。
input <- c("c","d","e","f")
test_function <- function(inputVec) {
df <- data.frame(inputVec[1], stringsAsFactors = FALSE)
names(df)[1] <- inputVec[1]
if(length(inputVec) == 1) {
return(df)
}
else if(length(inputVec) > 1) {
for(i in seq(2, length(inputVec), 1)) {
dfNew <- data.frame(inputVec[i], stringsAsFactors = FALSE)
names(dfNew) <- inputVec[i]
df <- dplyr::bind_cols(df, dfNew)
}
return(df)
}
}
testDF <- test_function(inputVec = input)
print(testDF)
## c d e f
##1 c d e f
如果我对你的问题的理解正确,那么你正在寻找一个创建函数的函数,其中第二个函数的参数名称与 input
中的名称(给第一个函数)和值一样,也许数字,由这些参数标记。如果没错,这个怎么样?
create_fun <- function(input) {
funargs <- paste(input, collapse=', ')
dfargs <- paste0(input, '=', input, collapse=', ')
funstr <- paste0(
sprintf("function(%s) {", funargs),
sprintf("data.frame(%s)", dfargs),
"}")
eval(parse(text=funstr))
}
# example applications:
create_fun(c('a','b'))(a=1, b=8)
## a b
## 1 1 8
create_fun(c('x','y','z'))(y=1, z=8, x=4)
## x y z
## 1 4 1 8
一个迟到的答案——可能对最初的问题没有用,但我还是把它贴出来了,因为我花了一点时间来弄清楚它:)。
一种方法是基于 rlang::new_function
中的代码:
doit <- function(i) {
args <- setNames(lapply(i, as.name),i)
fn <- call("function", as.pairlist(args), as.call(c(as.name("data.frame"), args)))
eval(fn, parent.frame())
}
# output
> doit("A")
function (A = A)
data.frame(A = A)
> doit(c("A", "B"))
function (A = A, B = B)
data.frame(A = A, B = B)
> doit(c("A", "B", "C"))
function (A = A, B = B, C = C)
data.frame(A = A, B = B, C = C)
我正在围绕 rBayesianOptimization
和 caret
R 包编写一个包装函数。下面描述的问题是主包装函数内部步骤的一部分。我需要将特定模型的超参数(这是下面 input
表示的)传递给将在高斯过程模型中采样的函数。超参数当前存储在字符向量中。
有没有办法在 R 中使用字符向量动态生成函数?我需要一个实际上创建另一个函数的函数。例如,
# start with this...
input <- c("a","b")
# ...and an intermediate function generates this
test_function <- function(a=a,b=b) {
d <- data.frame(a=a,b=b)
}
此外,该解决方案需要能够处理各种长度和内容的输入。所以这样的事情也应该有效,
# start with this...
input <- c("c","d","e","f")
# ...and an intermediate function generates this
test_function <- function(c=c,d=d,e=e,f=f) {
d <- data.frame(c=c,d=d,e=e,f=f)
}
这是一个玩具示例,但足以回答我的问题。
这是对您发布的简单示例的简单回答。听起来您的实际工作可能需要更复杂的方法,但这可能会有所帮助。我敢肯定还有其他方法可以更快地做到这一点。
input <- c("c","d","e","f")
test_function <- function(inputVec) {
df <- data.frame(inputVec[1], stringsAsFactors = FALSE)
names(df)[1] <- inputVec[1]
if(length(inputVec) == 1) {
return(df)
}
else if(length(inputVec) > 1) {
for(i in seq(2, length(inputVec), 1)) {
dfNew <- data.frame(inputVec[i], stringsAsFactors = FALSE)
names(dfNew) <- inputVec[i]
df <- dplyr::bind_cols(df, dfNew)
}
return(df)
}
}
testDF <- test_function(inputVec = input)
print(testDF)
## c d e f
##1 c d e f
如果我对你的问题的理解正确,那么你正在寻找一个创建函数的函数,其中第二个函数的参数名称与 input
中的名称(给第一个函数)和值一样,也许数字,由这些参数标记。如果没错,这个怎么样?
create_fun <- function(input) {
funargs <- paste(input, collapse=', ')
dfargs <- paste0(input, '=', input, collapse=', ')
funstr <- paste0(
sprintf("function(%s) {", funargs),
sprintf("data.frame(%s)", dfargs),
"}")
eval(parse(text=funstr))
}
# example applications:
create_fun(c('a','b'))(a=1, b=8)
## a b
## 1 1 8
create_fun(c('x','y','z'))(y=1, z=8, x=4)
## x y z
## 1 4 1 8
一个迟到的答案——可能对最初的问题没有用,但我还是把它贴出来了,因为我花了一点时间来弄清楚它:)。
一种方法是基于 rlang::new_function
中的代码:
doit <- function(i) {
args <- setNames(lapply(i, as.name),i)
fn <- call("function", as.pairlist(args), as.call(c(as.name("data.frame"), args)))
eval(fn, parent.frame())
}
# output
> doit("A")
function (A = A)
data.frame(A = A)
> doit(c("A", "B"))
function (A = A, B = B)
data.frame(A = A, B = B)
> doit(c("A", "B", "C"))
function (A = A, B = B, C = C)
data.frame(A = A, B = B, C = C)