2017-05-29 83 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 
相關問題