我在R中有一个大功能,用户可以不包含/指定一个对象。如果他们这样做,代码会检查以确保该对象中的名称与另一个名称中的名称匹配。如果他们不在,那么就没有必要进行检查。代码行是:
if(exists("grids")) if(!all(expvarnames %in% names(grids))) {stop("Not all expvar column names found as column names in grids")}
但我收到以下错误:
Error in match(x, table, nomatch = 0L) : argument "grids" is missing, with no default
在这次试运行中,网格被忽略了。如果我试试
if(exists("grids")) print("yay")
然后没有打印,即没有网格意味着表达式没有得到评估,这正如我所期望的那样。那么有谁能想到为什么R似乎正在评估主要例子中的后续IF语句?我应该在第二个周围拍一组大括号吗?
谢谢!
编辑:更多问题。删除"网格,"从函数变量列表中可以看出,如果没有被称为网格的对象,并且你没有在调用中指定它(即function(x,grids=whatever)
),它就可以工作。并保持"网格,"在变量的函数列表中,如果有一个名为grid的对象并且你在调用中指定了它,它就可以工作。
请参阅:http://i.imgur.com/9mr1Lwi.png
使用exists(grids)
是因为存在需要"引用"如果没有,一切都会失败。与他们("网格"),我需要决定是否保持"网格,"在功能列表中。如果我不这样做,但是我在调用(function(x,grids=whatever))
中指定了它,那么我将使用未使用的参数失败。如果我这样做,但是没有在通话中指定它,因为网格不存在而且我不想使用它,我得到匹配错误,网格缺少默认值。
我如何解决这个问题?也许在函数变量列表中将其列为grids="NULL"
,然后而不是if(exists("grids"))
执行if(grids!="NULL")
我仍然不知道为什么原来的匹配问题正在发生。匹配来自expvarnames / grid名称检查器,它是AFTER if(exists("grids"))
,其评估结果为FALSE。 WAaaaaaaiiiiittttt .....如果我在函数变量列表中指定网格,即简单地放置function(x,grids,etc){do stuff}
,这是否意味着函数在其环境中创建一个名为网格的对象?
男人,这是如此......
testfun <- function(x,grids)
{if(exists("grids")) globalgrids<<-grids
print(x+1)}
testfun(1) # Error in testfun(1) : argument "grids" is missing, with no default
testfun <- function(x,grids)
{if(exists("grids")) a<<-c(1,2,3)
print(x+1)}
testfun(1) #2 (and globally assigns a)
所以在第一个例子中,函数似乎创建了一个名为&#34; grid&#34;因为存在(&#34;网格&#34;)评估为真。但是,那么,在相同的路线上,当被要求用网格做某事时,它说它不存在!施罗丁格的对象?! 这在示例2中得到证明:网格评估为真,a是全局分配,然后函数执行其操作。疯狂。完全疯了。有谁知道为什么这种荒谬的事情发生了?并且是使用我的网格的最佳解决方案=&#34; NULL&#34;默认在函数变量列表中? 感谢。
可重复的例子,如果你愿意,但我已经为每一个排列都做过了:
testfun <- function(x,grids)
{if(exists("grids")) if(!all(expvarnames %in% names(grids))) {stop("Not all expvar column names found as column names in grids")}
print(x+1)}
testfun(1)
testfun(x=1,grids=grids)
grids<-data.frame(c(1,2,3),c(1,2,3),c(1,2,3))
expvarnames <- c("a","b","c")
colnames(grids) <- c("a","b","c")
答案 0 :(得分:2)
<强>解决方案强>
调整您的示例使用:
testfun <- function(x,grids = NULL)
{
if(!is.null(grids)){
if(!all(expvarnames %in% names(grids))){
stop("Not all expvar column names found as column names in grids")
}
print(x+1)
}
}
使用此testfun(1)
将不返回任何内容。通过在函数中指定默认参数NULL
,函数然后检查这个(即没有指定参数),然后如果是,则不继续该函数。
出现问题的原因
我们仔细阅读每个例子:
testfun <- function(x,grids)
{if(exists("grids")) globalgrids<<-grids
print(x+1)}
testfun(1) # Error in testfun(1) : argument "grids" is missing, with no default
这里我们调用函数testfun
,只给出x
参数。 testfun
知道它需要两个参数,因此创建局部变量x
和grids
。然后我们给x
一个参数,因此它将值赋给x
。 grids
没有参数,但是仍然创建了变量,即使没有赋值。所以grids
存在,但没有价值。
此exists("grids")
将TRUE
,但当我们尝试globalgrids<<-grids
时,我们会收到错误,因为grids
尚未分配值,因此我们无法为globalgrids
分配任何内容。
testfun <- function(x,grids)
{if(exists("grids")) a<<-c(1,2,3)
print(x+1)}
testfun(1) #2 (and globally assigns a)
但这很好。 grids
与前一种情况一样存在,我们实际上从未尝试访问grids
中存储的值,这会导致错误,因为我们还没有分配错误。
在解决方案中,我们只设置grids
的默认值,这意味着每当我们尝试访问变量时,我们总能得到一些东西。与之前的情况不同,我们将获得NULL
,而不是存储任何内容。
这一点的主要意义在于,当您在函数中声明参数时,每次使用该函数时都会创建它们。他们存在。但是,如果您没有在函数调用中为它们分配值,那么它们将存在,但没有任何值。然后当你尝试使用它们时,它们缺少值会引发错误。
答案 1 :(得分:1)
> a <- c(1,2,3,4)
> b <- c(2,4,6,8)
> if(exists("a")) if(!all(a %in% b)) {stop("Not all a in b")}
Error: Not all a in b
> rm(a)
> if(exists("a")) if(!all(a %in% b)) {stop("Not all a in b")}
>
如果a
不存在,则表达式不会按预期进行评估。在测试第一个表达式之前,请通过在控制台中运行grids
来确保rm(grids)
不存在。
答案 2 :(得分:0)
Richard Scriven的评论让我思考:网格是我的函数中的一个参数但是是可选的,所以也许不应该指定(就像“......”可选函数中的任何东西)。我评论了它并且它起作用了。万岁,为每个人欢呼。