【问题标题】:Trouble passing on an argument to function within own function在自己的函数中将参数传递给函数时遇到问题
【发布时间】:2013-02-02 17:40:08
【问题描述】:

我正在编写一个函数,我想在其中将一些参数传递给 crrstep 函数('crrstep' 包),但我遇到了一个问题:我的函数中的参数 'event' 在我输入时无法识别在 crrstep 中。我猜 crrstep 看起来与我希望它看起来的环境不同,但是即使在网上搜索了几个小时的解决方案后,我似乎也无法弄清楚如何解决这个问题(我在编程方面非常缺乏经验..) .任何帮助将不胜感激!

这是一些模拟数据(来自 crrstep-documentation 的调整示例)和我的代码示例:

n <- 500
ftime <- rexp(n)
fstatus <- sample(0:2,n,replace=TRUE)
testdata <- matrix(runif(8*n),nrow=n)
testdata <- cbind(ftime,fstatus,testdata)
dimnames(testdata)[[2]] <- c('ftime','fstatus','x1','x2','x3','x4','x5','x6','x7','x8')
testdata <- as.data.frame(testdata)
formula1 <- ftime ~ 1 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8
rm(fstatus,ftime,n)

test.fun <- function(x,data,event){
require(crrstep)
select.mod<- crrstep(formula=x,,etype=event, failcode=1, cencode=0,data=data, 
                   direction = "backward", criterion = "AIC", crr.object = TRUE, 
                   trace = FALSE)
#Rest of function omitted for now
print(select.mod)
}

#Test
test.fun(x=formula1,data=testdata,event=fstatus) 
#I get: Error in eval(expr, envir, enclos) : object 'event' not found"

非常感谢! 抢

【问题讨论】:

  • 问题是你 rm(fstatus) 在将它作为 event 参数传递给你的函数之前......
  • 嗨,juba,在我删除 fstatus 之前,我将它添加到了 testdata,然后我在我的函数中将其用作“数据”参数。我以为 crrstep 会在“数据”中查找“事件”(我也将其传递给 crrstep),但不知何故它没有..
  • 那么您应该在您的crrstep() 调用中使用etype=data[,event],并将fstatus 参数作为字符串传递:event="fstatus"。
  • 当我这样输入时:test.fun &lt;- function(x,data,event){ require(crrstep) select.mod&lt;- crrstep(formula=x,,etype=data[,event], failcode=1, cencode=0,data=data, direction = "backward", criterion = "AIC", crr.object = TRUE, trace = TRUE) print(select.mod) } test.fun(x=formula1,data=testdata,event="fstatus") 我仍然得到一个错误:错误在'[.data.frame'(data, , event) : object 'event' not found
  • 这两个最近的问题是相关的,也可能有帮助:stackoverflow.com/q/14784302/210673stackoverflow.com/q/14839689/210673

标签: r function environment argument-passing


【解决方案1】:

在依赖于数据帧内评估名称的函数中调用函数时,我使用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 而不使用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)'

【讨论】:

  • 嗨 Aaron,感谢您的清晰解释,这个解决方案对我来说非常有效!
  • @aaron 这非常有趣,非常感谢您的详细解释。但现在我头疼:)
【解决方案2】:

我不清楚为什么,但是如果您将 etype 参数作为索引数据框传递,它似乎会失败。但是,如果您事先创建矢量,它似乎可以工作:

test.fun <- function(x,data,event){
  require(crrstep)
  etype <- data[,event]
  select.mod<- crrstep(formula=x,data=data,etype=etype, failcode=1, cencode=0, 
                   direction = "backward", criterion = "AIC", crr.object = TRUE, 
                   trace = FALSE)
#Rest of function omitted for now
print(select.mod)
}

【讨论】:

  • 有趣的是,它似乎对我不起作用;我仍然收到Error in '[.data.frame'(data, , event) : object 'event' not found 消息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 2015-01-07
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
  • 2012-06-17
相关资源
最近更新 更多