麻烦传递一个参数在自己的函数内运行 [英] Trouble passing on an argument to function within own function

查看:101
本文介绍了麻烦传递一个参数在自己的函数内运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个函数,我想将一些参数传递给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)
#现在遗漏的功能
print(select.mod)
}

#Test
test.fun(x = formula1,data = testdata,event = fstatus)
#I get:eval中的错误(expr,envir,enclos):object'event'not找到

非常感谢!
Rob

解决方案

在函数内调用依赖于数据框中名称评估的函数时,我使用 do.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)告诉我们e给函数的名称,而不是名称 event as.name(data)指示它在函数中寻找 data ,而不是传递实际的数据帧。另一个选项是 substitute(data),它将查找您拥有的实际数据框。 使用 lm

下面是使用 lm 权重参数:

以下是一个示例数据集和对 lm ,不在另一个函数中。我打印响应的调用元素以查看它实际做了什么。

 > 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,权重= z,data = dd)$ call
lm(formula = y〜x,data = dd,weights = z)

自然的方式,因为它在数据框中寻找 w ,所以不起作用:

 > f1 < - 函数(f,w,d){
+ lm(公式= f,权重= w,数据= d)
+}
> f1(y〜x,z,dd)
eval中的错误(expr,envir,enclos):找不到对象'w'

可以使用字符串构建调用;这是一个更直截了当的:

 > f2 < - 函数(f,w,d){
+ do.call(lm,list(formula = as.formula(f),weights = as.name(w),data = as。姓名(d)))
+}
> f2(y〜x,z,dd)$ call
lm(formula = y〜x,data = dd,weights = z)

或者可以使用替代;在这里我调用函数中的实际数据集 dd ,而不是函数内的 d 。如果我想使用 update ,这可能会很有用。

 > ; f3 < - 函数(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 < - 函数(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 < - 函数(f,w,d){
+ do.call(lm,list(formula = f,weights = substitute(w),data = d))
+}
> f5(y〜x,z,dd)$ call
lm(公式= y〜x,data = list(x = 1:10,y = c(9.2,11.4,8.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)),权重= z)

再次证明您不能只使用替换 do.call ,因为 substitute 会在 lm

 > (公式= f,权重=替代(w),数据= d)
+}
>(函数(f,w,d) f6(y〜x,z,dd)
model.frame.default中的错误(公式= f,data = d,weights = substitute(w),:
变量的无效类型(符号) (权重)'


I am writing a function in which I want to pass some arguments to the crrstep-function ('crrstep' package), but I encountered a problem: somehow the argument 'event' in my function is not recognized when I enter it in crrstep. I guess that crrstep looks in a different environment than the one I want it to look, but even after hours of searching for solutions on the web, I cannot seem to figure out how to solve this (I am quite inexperienced in programming..). Any help would be greatly appreciated!

Here is some simulation data (adjusted example from crrstep-documentation) and an example of my code:

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"

Many thanks! Rob

解决方案

When calling functions within functions that depend on evaluating names within a data frame, I use do.call, which evaluates its arguments before passing to the function and so makes both debugging and writing the code simpler, and I feel like I can be more sure about what it's doing. (For debugging, just use call instead of do.call, which will show what the function will try to run; the syntax is also a little different so when doing this remove the list structure within the call as well.)

(Credit to Josh O'Brien's answer here for this idea: https://stackoverflow.com/a/7668846/210673)

In this case, it would look like this:

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) 

The substitute(event) tells it to use the name that was given to the function, not the name event. The as.name("data") tells it to look for data within the function instead of passing the actual data frame. Another option is substitute(data) which will look for the actual data frame you have.

an example using lm

Here's an example of very similar behavior using lm and the weights argument:

Here's an example data set and the call to lm, not within another function. I print the call element of the response to see what it actually did.

> 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)

The natural way, which doesn't work because it's looking for w in the data frame:

> 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

One can build the call with strings; this is a little more straightforward:

> 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)

Or one can use substitute; here I'm calling the function on my actual data set dd, not the d within the function. This might be useful later if I want to use 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)

But I could also use d within the function; this time notice that data = d in the call instead of 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)

It works to put in the actual data frame as well, but the call is longer. This however, might be desired if you're changing the data frame programatically before each call and want to have a record of what that data frame is. (My preference, though, would be to save that data frame in a more explicit way, if you really do want it later.)

> 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)

One more to show that you can't just use substitute without do.call as the substitute is executed within the call to 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)'

这篇关于麻烦传递一个参数在自己的函数内运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆