R:IF语句评估表达式,尽管条件为FALSE?

时间:2015-08-19 17:18:36

标签: r if-statement nested match

我在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")

3 个答案:

答案 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知道它需要两个参数,因此创建局部变量xgrids。然后我们给x一个参数,因此它将值赋给xgrids没有参数,但是仍然创建了变量,即使没有赋值。所以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的评论让我思考:网格是我的函数中的一个参数但是是可选的,所以也许不应该指定(就像“......”可选函数中的任何东西)。我评论了它并且它起作用了。万岁,为每个人欢呼。