我有以下问题:我想编写一个函数,该函数应该获得多个相似的输入集,比方说:

FUN <- function(part1.x, part1.y, part1.z, part2.x, part2.y, part2.z){}

因此,每个部分的变量是相同的,但它们可以有不同的值.我的第一次try 就是这样使用它们,但输入的数量增加了,看起来相当复杂.我的下一个 idea 是将变量存储为向量,并使用元素的位置来指示它们属于哪个部分

FUN <- function(x, y, z){},其中每个输入是一个向量c[part1, part2].这是更好的,但我发现很难在部件之间交换输入,感觉有点困惑.

我最喜欢的 idea 是在处理方面和用户友好性方面存储一个列表,其中包含每个部分的输入,例如

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")){}

如果用户 Select FUN(part1 = list(y = FALSE), part2 = list(x = 2)),则忽略part1$xpart1$zpart2$ypart2$z的缺省值,并在覆盖整个列表时不存在变量.

作为一种解决办法,我 for each 部分编写了一个函数,该函数基本上就是用来存储和返回默认值的:

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))
} 

然后在Main函数中调用它们以检索缺省值,然后通过名称相等将这些缺省值与提供的输入组合:

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".

所以我的问题是:

  1. 像我这样处理多个类似输入值的最佳方式是什么?我觉得我可能错过了什么.有没有必go 之路?

如果不是这样的话:

  1. 我的方法是否比我已经提到的缺点更多-以及如何解决我发现的最好的缺点?

我发现这有些相关的帖子Get all Parameters as ListExtract the elements of list as individual arguments within custom function in r,但我不能让它工作,也想确保我在正确的道路上…

谢谢!

推荐答案

您可以使用do.call()将参数传递给帮助器函数,然后返回它们.这将填充默认设置并引发相应的错误.

part1_fun <- function(x = 1, y = TRUE, z = c("abc", "zyx")){
  z <- match.arg(z)
  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 = "zyx"), 
  part2_args = list(y = TRUE)
)
# $x
# [1] 3
# 
# $y
# [1] TRUE
# 
# $z
# [1] "zyx"
# 
# $x
# [1] 2
# 
# $y
# [1] TRUE
# 
# $z
# [1] "bcd"

参数拼写错误:

FUN(
  part1_args = list(xxy = 3, z = "zyx"), 
  part2_args = list(y = TRUE)
)
# Error in (function (x = 1, y = TRUE, z = c("abc", "zyx"))  : 
#   unused argument (xxy = 3)

match.arg()错误:

FUN(
  part1_args = list(x = 3, z = "x"), 
  part2_args = list(y = TRUE)
)
# Error in match.arg(z) : 'arg' should be one of “abc”, “zyx”

R相关问答推荐

提取R中值和列名的所有可能组合

从多个前置日期中获取最长日期

为什么当我try 在收件箱中使用合并功能时会出现回收错误?

查找图下的面积

如何在emmeans中计算连续变量的对比度

如何提取所有完美匹配的10个核苷酸在一个成对的匹配与生物字符串在R?>

使用for循环和粘贴创建多个变量

ComplexHEAT:使用COLUMN_SPLIT时忽略COLUMN_ORDER

用R ggplot2求上、下三角形中两个变量的矩阵热图

按多列统计频次

更改STAT_VALLES/STAT_PEAKS中的箭头线宽/大小

在数据帧列表上绘制GGPUP

创建列并对大型数据集中的特定条件进行成对比较的更高效程序

如何计算每12行的平均数?

使用ifElse语句在ggploy中设置aes y值

用满足特定列匹配的另一行替换NA行

变异以按组从其他列创建具有最大和最小值的新列

我正在try 创建一个接近cos(X)的值的While循环,以便它在-或+1-E10范围内

如何合并不同列表中的数据文件,包括基于名称的部分匹配,而不是一对一等价

如何将字符类对象中的数据转换为R中的字符串