在依赖于评估数据框中的名称的函数中调用函数时,我使用do.call
,它在传递给函数之前评估其参数,因此使调试和编写代码更简单,我觉得我可以更确定它是什么正在做。(对于调试,只需使用call
而不是do.call
,它将显示函数将尝试运行的内容;语法也略有不同,因此在执行此操作时也要删除调用中的列表结构。)
(感谢 Josh O'Brien 对这个想法的回答:https ://stackoverflow.com/a/7668846/210673 )
在这种情况下,它看起来像这样:
test.fun <- function(x, data, event){
require(crrstep)
select.mod <- do.call("crrstep",
list(formula=x, etype=substitute(event), failcode=1, cencode=0,
data=as.name("data"), direction = "backward", criterion = "AIC",
crr.object = TRUE, trace = FALSE))
print(select.mod)
}
test.fun(x=formula1, data=testdata, event=fstatus)
substitute(event)
告诉它使用赋予函数的名称,而不是名称event
。as.name("data")
告诉它在函数中查找而data
不是传递实际的数据帧。另一种选择是substitute(data)
查找您拥有的实际数据框。
使用示例lm
这是一个使用lm
和weights
参数的非常相似的行为示例:
这是一个示例数据集和对 的调用lm
,而不是在另一个函数中。我打印call
响应的元素以查看它实际上做了什么。
> set.seed(5)
> dd <- data.frame(x=1:10,y=round(rnorm(10,mean=10),1), z=round(runif(10,1,4),1))
> lm(y~x, weights=z, data=dd)$call
lm(formula = y ~ x, data = dd, weights = z)
自然的方式,它不起作用,因为它w
在数据框中寻找:
> f1 <- function(f,w,d){
+ lm(formula=f,weights=w, data=d)
+ }
> f1(y~x, z, dd)
Error in eval(expr, envir, enclos) : object 'w' not found
可以使用字符串构建调用;这更简单一点:
> f2 <- function(f,w,d){
+ do.call("lm", list(formula=as.formula(f), weights=as.name(w), data=as.name(d)))
+ }
> f2("y~x", "z", "dd")$call
lm(formula = y ~ x, data = dd, weights = z)
或者一个可以使用substitute
;在这里,我在我的实际数据集上调用该函数dd
,而不是d
在函数内。如果我想使用update
.
> f3 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=substitute(d)))
+ }
> f3(y~x, z, dd)$call
lm(formula = y ~ x, data = dd, weights = z)
但我也可以d
在函数内使用;这次请注意,data = d
在调用中而不是data = dd
.
> f4 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=as.name("d")))
+ }
> f4(y~x, z, dd)$call
lm(formula = y ~ x, data = d, weights = z)
它也可以放入实际的数据框,但调用时间更长。但是,如果您在每次调用之前以编程方式更改数据框并希望记录该数据框是什么,则可能需要这样做。(不过,如果您以后确实需要,我的偏好是以更明确的方式保存该数据框。)
> f5 <- function(f,w,d){
+ do.call("lm", list(formula=f, weights=substitute(w), data=d))
+ }
> f5(y~x, z, dd)$call
lm(formula = y ~ x, data = list(x = 1:10, y = c(9.2, 11.4, 8.7,
10.1, 11.7, 9.4, 9.5, 9.4, 9.7, 10.1), z = c(3.7, 3.2, 1.6, 1.7,
1.4, 2.4, 2.3, 3.9, 1.4, 3.9)), weights = z)
还有一个表明您不能只使用substitute
without do.call
,因为substitute
在调用lm
.
> f6 <- function(f,w,d){
+ lm(formula=f,weights=substitute(w), data=d)
+ }
> f6(y~x, z, dd)
Error in model.frame.default(formula = f, data = d, weights = substitute(w), :
invalid type (symbol) for variable '(weights)'