我想知道是否有一个Base R函数来提取在特定函数调用中使用的参数值?
例如,对于下面的每个对象x
,y
和z
,是否有提取参数名称的通用方法(例如n
,{正在使用{1}},sd
,rate
)和用户或系统为每个参数分配的值(例如,scale
1e4
)?
注意:在某些" R"这样的提取功能很容易完成。例如,在n
中,可以使用density()
轻松提取参数values
。
density()$call
答案 0 :(得分:2)
这真的不是一件容易的事。如果您正在构建该功能,则可以使用match.call
捕获该呼叫,这可以解析而不会有太多麻烦:
f <- function(x, y = 1, ...){
cl <- match.call()
as.list(cl[-1])
}
str(f(1))
#> List of 1
#> $ x: num 1
str(f(1, 'foo'))
#> List of 2
#> $ x: num 1
#> $ y: chr "foo"
str(f(1, 'foo', list(3), fun = sum))
#> List of 4
#> $ x : num 1
#> $ y : chr "foo"
#> $ : language list(3)
#> $ fun: symbol sum
注意match.call
仅捕获来电,并且不会添加默认参数(第一个示例中没有y
)。可以使用formals(f)
访问这些内容,因为f
不是原始的,因此可以通过
user_args <- f(1)
fun_args <- formals(f)
fun_args[names(user_args)] <- user_args
str(fun_args)
#> List of 3
#> $ x : num 1
#> $ y : num 1
#> $ ...: symbol
这种方法对完成的点不起作用,但如果它们已经完成,那么match.call
本身就足够了。要提取传递给现有函数的参数,您可以编写一个包含match.call
的包装器,但重建每个函数几乎不可行,并且您捕获的调用无论如何都会看起来很有趣,除非您覆盖现有函数。只要函数不是原始函数,您就可以使用quote
启用formals
方法,但是:
cl <- quote(rnorm(5, 2))
user_args <- as.list(cl[-1]) # subset call to only args
fun_args <- formals(as.character(cl[1])) # subset call to only function
names(user_args) <- names(fun_args)[seq(length(user_args))]
fun_args[names(user_args)] <- user_args
str(fun_args)
#> List of 3
#> $ n : num 5
#> $ mean: num 2
#> $ sd : num 1
另一种方法是使用rlang,其函数可以很好地处理原语(fn_fmls(sum)
),可以轻松可靠地提取部分调用(lang_fn
,lang_args
),准确命名未命名的参数(lang_standardize
)等等。与purrr的新list_modify
(开发版)一起,这一切都变得相当轻松:
library(rlang)
fun_call <- quo(rnorm(5))
fun_call
#> <quosure: frame>
#> ~rnorm(5)
default_args <- fn_fmls(lang_fn(fun_call))
str(default_args)
#> Dotted pair list of 3
#> $ n : symbol
#> $ mean: num 0
#> $ sd : num 1
user_args <- lang_args(lang_standardise(fun_call))
str(user_args)
#> List of 1
#> $ n: num 5
calling_args <- purrr::list_modify(default_args, user_args)
str(calling_args)
#> Dotted pair list of 3
#> $ n : num 5
#> $ mean: num 0
#> $ sd : num 1