Shixiang Wang

>上士闻道
勤而行之

do.call的使用

王诗翔 · 2018-06-07

分类: r  
标签: r   do.call  

学习下R中一个有趣地函数,do.call

do.call这个函数是我在搜索问题时会看到别人经常使用的一个函数,心生好奇,这次来看看它的用法。

从文档来看,do.call可以通过名字构建和执行函数,并且将参数以列表的形式传入。

Description

do.call constructs and executes a function call from a name or a function and a list of arguments to be passed to it.

Usage

do.call(what, args, quote = FALSE, envir = parent.frame())

Arguments

what

either a function or a non-empty character string naming the function to be called.

args

a list of arguments to the function call. The names attribute of args gives the argument names.

quote

a logical value indicating whether to quote the arguments.

envir

an environment within which to evaluate the call. This will be most useful if what is a character string and the arguments are symbols or quoted expressions. 显然,前两个参数很重要,确定了该函数的一般用法,后两个参数涉及一些执行引用与环境的问题,这方面我懂的不多,不过基本也用不到。

下面通过例子学习下使用。

例子

# 生成一个复数序列
do.call("complex", list(imag = 1:3))
## [1] 0+1i 0+2i 0+3i
# 如果我们有一个列表(比如数据框)
# 我们需要使用c()添加更多的参数
tmp <- expand.grid(letters[1:2], 1:3, c("+", "-"))
tmp
##    Var1 Var2 Var3
## 1     a    1    +
## 2     b    1    +
## 3     a    2    +
## 4     b    2    +
## 5     a    3    +
## 6     b    3    +
## 7     a    1    -
## 8     b    1    -
## 9     a    2    -
## 10    b    2    -
## 11    a    3    -
## 12    b    3    -
do.call("paste", c(tmp, sep=""))
##  [1] "a1+" "b1+" "a2+" "b2+" "a3+" "b3+" "a1-" "b1-" "a2-" "b2-" "a3-" "b3-"
#do.call("paste", list(tmp, sep=""))
do.call(paste, list(as.name("A"), as.name("B")), quote = TRUE)
## [1] "A B"
do.call(paste, list(as.name("A"), as.name("B")), quote = TRUE)
## [1] "A B"
# 这个例子中,A、B被转换为了符号对象,如果不quote起来就会报错
#do.call(paste, list(as.name("A"), as.name("B")), quote = FALSE)
# 当然你如果直接使用下面这个语句结果是一样的,不过这里是介绍quote的用法
do.call(paste, list("A", "B"))
## [1] "A B"

从哪里寻找对象的例子:

A <- 2
f <- function(x) print(x ^ 2)
env <- new.env()
assign("A", 10, envir = env)
assign("f", f, envir = env)
f <- function(x) print(x)
f(A)
## [1] 2
# 使用当前环境函数与变量
do.call("f", list(A))
## [1] 2
# 使用env环境函数与当前环境变量
do.call("f", list(A), envir = env)
## [1] 4
# 使用当前环境函数与变量 
do.call(f, list(A), envir = env)
## [1] 2
# 使用env环境函数与env环境变量
do.call("f", list(quote(A)), envir = env)
## [1] 100
# 使用当前环境函数与env环境变量 
do.call(f, list(quote(A)), envir = env)
## [1] 10
# 使用env环境函数与env环境变量
do.call("f", list(as.name("A")), envir = env)
## [1] 100
eval(call("f", A))
## [1] 2
eval(call("f", quote(A)))
## [1] 2
eval(call("f", A), envir = env)
## [1] 4
eval(call("f", quote(A)), envir = env)
## [1] 100

上面例子多,需要仔细揣摩参数变化后结果的变化。首先在新环境创建的函数对象是打印输入的平方,A是10。

call函数用来创建和测试对象,不过看起来用法与quote()类似,将东西先存起来不执行,等后续调用。

A <- 10.5
wait <- call("round", A)
eval(wait)
## [1] 10