我有以下问题:我想编写一个应该获得多个相似输入集的函数,可以说:
FUN <- function(part1.x, part1.y, part1.z, part2.x, part2.y, part2.z){}
所以每个部分的变量是相同的,但它们可以有不同的值。我的第一次尝试是像这样使用它们,但是输入的数量不断增加,而且看起来非常复杂。我的下一个想法是将变量存储为向量,并使用元素的位置来指示它们属于哪个部分,例如
FUN <- function(x, y, z){}
,其中每个输入都是一个向量c[part1, part2]
。这更好,但我发现很难在部件之间交换输入,感觉有点混乱。
我最喜欢的处理方式和用户友好性的想法是存储一个包含每个部分输入的列表,例如
FUN <- function(part1 = list(x, y, z), part2 = list(x, y, z){}
这里的问题是,似乎不可能将默认值与用户输入结合起来,因此当函数读取时:
FUN <- function(part1 = list(x = 1, y = TRUE, z = "abc"), part2 = list(x = 2, y = FALSE, z = "bcd")){}
并且用户执行
FUN(part1 = list(y = FALSE), part2 = list(x = 2))
,则对于 part1$x
、part1$z
、part2$y
和 part2$z
,默认值将被忽略,并且随着整个列表被覆盖,变量不存在。
作为解决方法,我为每个部分编写了一个函数,该函数基本上只是用于存储和返回默认值:
part1_fun <- function(x = 1, y = TRUE, z = "abc"){
return(formals(part1_fun))
}
part2_fun <- function(x = 2, y = FALSE, z = "bcd"){
return(formals(part2_fun))
}
然后在主函数中调用它来检索默认值,然后通过名称相等性与提供的输入进行组合:
FUN <- function(part1_args, part2_args){
part1_default <- part1_fun(part1_args)
part2_default <- part2_fun(part2_args)
common_names_part1 <- intersect(names(part1_args), names(part1_default ))
common_names_part2 <- intersect(names(part2_args), names(part2_default ))
part1_input <- part1_default
part1_input[common_names_part1] <- part1_args[common_names_part1]
part2_input <- part2_default
part2_input[common_names_part2] <- part2_args[common_names_part2]
print(part1_input)
print(part2_input)
}
FUN(part1_args = list(x = 3, z = "a"), part2_args = list(y = TRUE))
这可行(但感觉像是一种黑客),因为它然后使用所有值(默认值和用户提供的值),但是我已经看到的一个缺点是它不会捕获拼写错误的输入,如果我没有捕获它就会忽略它分别那个。另一个是我目前没有找到一种方法可以让 match.arg 在这种情况下工作以允许更短的输入字符串。因此,当 z 可以是两个字符串
part1_fun <- function(x = 1, y = TRUE, z = c("abc", zyx")){
之一时,在此函数中添加 z = match.arg(z)
不会导致用户输入 FUN(part1_args = list(z = "a"))
转换为 z == "abc"。相反,它仍然是“a”。
所以我的问题:
如果情况并非如此:
我发现这个有点相关的帖子获取所有参数作为列表和提取列表的元素作为r中自定义函数中的单独参数但我无法让它工作,并且还想确保我走在正确的轨道上根本...
谢谢!
基于
do.call()
的解决方案;等待match.arg()
处理和更多解释。
part1_fun <- function(x = 1, y = TRUE, z = "abc"){
list(x = x, y = y, z = z)
}
part2_fun <- function(x = 2, y = FALSE, z = "bcd"){
list(x = x, y = y, z = z)
}
FUN <- function(part1_args, part2_args){
part1_input <- do.call(part1_fun, part1_args)
part2_input <- do.call(part2_fun, part2_args)
print(part1_input)
print(part2_input)
}
FUN(part1_args = list(x = 3, z = "a"), part2_args = list(y = TRUE))
输出:
$x
[1] 3
$y
[1] TRUE
$z
[1] "a"
$x
[1] 2
$y
[1] TRUE
$z
[1] "bcd"