do.call 函数用于构造和执行一个函数调用,可以通过指定函数名称或函数对象以及一个包含参数的列表来实现。以下是其主要参数和用法:
what: 要调用的函数,可以是一个函数对象或一个非空的字符字符串,表示函数的名称。
args: 一个包含函数调用参数的列表。args列表的names属性提供参数的名称。
quote: 一个逻辑值,指示是否引用参数。如果设置为FALSE(默认值),则参数在调用环境中进行评估,如果设置为TRUE,则对每个参数进行引用。
envir: 一个环境,在其中进行调用的评估。如果what是一个字符字符串并且参数是符号或引用表达式,这可能会很有用。
以下是一些示例,演示如何使用do.call函数:
xxxxxxxxxxdo.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 的三个复数。
xxxxxxxxxxtmp <- 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 数据框的各列值按照指定规则连接在一起。
xxxxxxxxxxdo.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 在传递参数时对参数进行了引用,而不是对其进行求值。
xxxxxxxxxxA <- 2f <- 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:
xxxxxxxxxxA <- 2f <- function(x) print(x^2)在全局环境中定义了一个变量 A,其值为2,以及一个函数 f,该函数接收一个参数 x,并打印 x^2。
创建新的环境 env:
xxxxxxxxxxenv <- new.env()使用 new.env() 函数创建了一个新的环境对象 env。
在新环境中重新定义 A 和 f:
xxxxxxxxxxassign("A", 10, envir = env)assign("f", f, envir = env)使用 assign 函数在环境 env 中重新定义了变量 A 的值为10,并将函数 f 赋值给了环境 env 中的同名函数。
使用 do.call 调用函数 f:
xxxxxxxxxxdo.call("f", list(A), envir = env)do.call 调用了函数 f,并将参数列表 list(A) 传递给了 f 函数。此时,A 是环境 env 中的变量,其值为10。
因此,f(10) 就相当于执行 print(10^2),结果为 100。所以,最后的输出是 100。
总的来说,这段代码演示了如何在一个指定的环境中使用 do.call 来调用一个函数,并且该函数可以在指定环境中找到其定义的变量。