2017-05-29 85 views
1

我想知道是否有一个Base R函数来提取在特定函数调用中使用的参数值?如何找出在R函数调用中使用了哪些参数值?

例如,对于每个对象xy和下面z的,是有一个通用的方法来提取参数名称(例如,nsdratescale)在使用中和的值(例如,1e4为)由用户或系统分配给每个参数?

注意:在某些“R”功能,这种提取很容易完成。例如,在density()中,可以使用density()$call轻松提取参数values

x = rnorm(n = 1e4, mean = 2, sd = 4) 
y = rlogis(1e4, 20) 
z = rexp(1e4, 5) 
+1

据我所知,你必须保存该调用并解析它,这是一种痛苦。 – alistaire

+1

@alistaire说,你可以使用'Sys.call()'来访问一个函数内部的调用......但是你的目标是什么? – Val

回答

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 
相关问题