do.call的使用
王诗翔 · 2018-06-07
学习下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