do.call
函数用于构造和执行一个函数调用,可以通过指定函数名称或函数对象以及一个包含参数的列表来实现。以下是其主要参数和用法:
what: 要调用的函数,可以是一个函数对象或一个非空的字符字符串,表示函数的名称。
args: 一个包含函数调用参数的列表。args列表的names
属性提供参数的名称。
quote: 一个逻辑值,指示是否引用参数。如果设置为FALSE(默认值),则参数在调用环境中进行评估,如果设置为TRUE,则对每个参数进行引用。
envir: 一个环境,在其中进行调用的评估。如果what是一个字符字符串并且参数是符号或引用表达式,这可能会很有用。
以下是一些示例,演示如何使用do.call
函数:
xxxxxxxxxx
do.call("complex", list(imaginary = 1:3))
这代码的含义是构造并执行一个调用 complex
函数的操作。
解释如下:
complex
函数: complex
是一个内置的 R 函数,用于创建复数。复数由实部和虚部组成。在这个上下文中,complex
函数将一组虚部作为参数,返回相应虚部的复数。
do.call
函数: do.call
函数用于将函数调用作为参数传递给另一个函数并执行。它的第一个参数是一个函数或函数名,第二个参数是一个参数列表。
参数列表: list(imaginary = 1:3)
是一个包含一个元素的列表,该元素是一个整数向量 1:3
。在复数的上下文中,这将被解释为虚部的值。imaginary
是一个参数名,它指定了这个参数的名称。
因此,do.call("complex", list(imaginary = 1:3))
的执行过程如下:
do.call
将调用 complex
函数,并将 list(imaginary = 1:3)
中的参数传递给 complex
函数。
complex
函数接收到这个参数,创建了包含虚部为 1、2 和 3 的复数。
这段代码的结果将是一个复数的向量,表示虚部分别为 1、2 和 3 的三个复数。
xxxxxxxxxx
tmp <- expand.grid(letters[1:2], 1:3, c("+", "-"))
do.call("paste", c(tmp, sep = ""))
这段代码的含义是使用 do.call
函数来调用 paste
函数,并将 tmp
数据框的列作为参数传递给 paste
函数。
让我们详细解释:
expand.grid
函数: expand.grid
用于创建一个包含所有给定变量组合的数据框。在这里,letters[1:2]
生成字母 "a" 和 "b",1:3
生成数字 1、2 和 3,c("+", "-")
生成字符向量 "+", "-"。expand.grid
将这些变量的所有组合组成一个数据框 tmp
。
xxxxxxxxxx
# 结果:
# 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
函数: do.call
用于执行一个函数调用。第一个参数是要调用的函数(这里是 "paste"),第二个参数是传递给该函数的参数列表。
参数列表: c(tmp, sep = "")
将 tmp
数据框的每一列作为参数传递给 paste
函数。 sep = ""
指定了 paste
函数的 sep
参数,表示在连接字符时不使用分隔符。
所以,do.call("paste", c(tmp, sep = ""))
的执行过程如下:
do.call
调用 paste
函数,并将 tmp
数据框的每一列作为参数传递给 paste
函数。
paste
函数接收到这些参数,将每一行的值连接在一起,使用空字符串作为分隔符,形成一个字符向量。
最终结果是一个包含连接后的字符串的字符向量:
xxxxxxxxxx
[1] "a1+" "b1+" "a2+" "b2+" "a3+" "b3+" "a1-" "b1-" "a2-" "b2-" "a3-" "b3-"
这表示将 tmp
数据框的各列值按照指定规则连接在一起。
xxxxxxxxxx
do.call(paste, list(as.name("A"), as.name("B")), quote = TRUE)
这段代码的含义是使用 do.call
函数调用 paste
函数,将 as.name("A")
和 as.name("B")
作为参数传递给 paste
函数,并在传递参数时对参数进行引用。
让我们详细解释:
do.call
函数: do.call
用于执行一个函数调用。第一个参数是要调用的函数(这里是 paste
),第二个参数是传递给该函数的参数列表。
参数列表: list(as.name("A"), as.name("B"))
创建一个包含两个元素的列表。每个元素都是 as.name
函数的调用,将字符 "A" 和 "B" 转换为符号。在这个上下文中,as.name
用于创建符号对象,使得参数传递时可以保持原始字符的引用。
quote 参数: quote = TRUE
指定了在传递参数时对参数进行引用。这意味着 do.call
不会对参数进行求值,而是保持它们作为符号的形式。
因此,do.call(paste, list(as.name("A"), as.name("B")), quote = TRUE)
的执行过程如下:
do.call
调用 paste
函数,并将 list(as.name("A"), as.name("B"))
中的参数传递给 paste
函数。
paste
函数接收到这两个参数,由于 quote = TRUE
,它会保持这两个参数的符号形式而不进行求值。
最终结果是一个符号向量,表示传递给 paste
函数的两个参数的符号形式:
xxxxxxxxxx
[1] A B
这个符号向量反映了 do.call
在传递参数时对参数进行了引用,而不是对其进行求值。
xxxxxxxxxx
A <- 2
f <- function(x) print(x^2)
env <- new.env()
assign("A", 10, envir = env)
assign("f", f, envir = env)
do.call("f", list(A), envir = env) # 4
这段代码的含义是在指定环境中使用 do.call
函数调用一个函数。
让我们逐步解释:
定义全局变量 A
和函数 f
:
xxxxxxxxxx
A <- 2
f <- function(x) print(x^2)
在全局环境中定义了一个变量 A
,其值为2,以及一个函数 f
,该函数接收一个参数 x
,并打印 x^2
。
创建新的环境 env
:
xxxxxxxxxx
env <- new.env()
使用 new.env()
函数创建了一个新的环境对象 env
。
在新环境中重新定义 A
和 f
:
xxxxxxxxxx
assign("A", 10, envir = env)
assign("f", f, envir = env)
使用 assign
函数在环境 env
中重新定义了变量 A
的值为10,并将函数 f
赋值给了环境 env
中的同名函数。
使用 do.call
调用函数 f
:
xxxxxxxxxx
do.call("f", list(A), envir = env)
do.call
调用了函数 f
,并将参数列表 list(A)
传递给了 f
函数。此时,A
是环境 env
中的变量,其值为10。
因此,f(10)
就相当于执行 print(10^2)
,结果为 100
。所以,最后的输出是 100
。
总的来说,这段代码演示了如何在一个指定的环境中使用 do.call
来调用一个函数,并且该函数可以在指定环境中找到其定义的变量。