【问题标题】:R: IF statement evaluating expression despite condition being FALSE?R:IF 语句评估表达式,尽管条件为 FALSE?
【发布时间】:2015-08-19 17:18:35
【问题描述】:

我在 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)),它会起作用。并且在变量的函数列表中保留“网格”意味着如果有一个名为网格的对象并且您确实在调用中指定了它,它就可以工作。

请看这个:http://i.imgur.com/9mr1Lwi.png

使用 exists(grids) 已被淘汰,因为存在需要“引号”,而没有 em 一切都会失败。有了它们(“网格”),我需要决定是否在函数列表中保留“网格”。如果我不这样做,但我在调用 (function(x,grids=whatever)) 中指定它,那么我会得到未使用的参数失败。如果我这样做了,但由于网格不存在并且我不想使用它而没有在调用中指定它,我会收到匹配错误,网格缺少默认值。

我该如何解决这个问题?也许在函数变量列表中将其列为grids="NULL",而不是if(exists("grids"))if(grids!="NULL")

我仍然不知道为什么会发生原始匹配问题。匹配来自 expvarnames/grids 名称检查器,它位于 if(exists("grids")) 之后,其计算结果为 FALSE。 WAaaaaaaaiiiiittttt..... 如果我在函数变量列表中指定网格,即简单地放置function(x,grids,etc){do stuff},这是否意味着函数在其环境中创建了一个名为网格的对象? 伙计,这太f'd了....

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)

所以在第一个示例中,该函数似乎创建了一个名为“grids”的对象,因为 exists("grids") 的计算结果为 true。但是,在同一条线上,当被要求用网格做某事时,它说它不存在!薛定谔的对象?! 这在示例 2 中得到了证明:grids 评估为 true,并且 a 被全局分配,然后函数执行其操作。疯狂。彻底的疯狂。有谁知道为什么会发生这种荒谬的事情?在函数变量列表中使用我的 grids="NULL" 默认值的最佳解决方案是什么? 谢谢。

可重现的示例,如果您愿意,但我已经为每个排列完成了:

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

【问题讨论】:

  • 您能否提供一个可重现的示例。 argument "grids" is missing, with no default 很有趣也很可疑。 grids 是你函数的参数吗?
  • 我怀疑“网格”不应该有引号
  • 不幸的是,我最初尝试不带引号,但得到:“存在错误(网格):找不到对象'网格'”。这就是我想要的......但是错误破坏了代码! Grids 是我的函数的参数,是的,没有默认值,所以在函数的元素列表中简单地“...,网格,...”。
  • Richard 的评论让我想到:grids 是我的函数中的一个参数,但它是可选的,所以可能不应该指定(就像“...”可选函数中的任何内容一样)。我把它注释掉了,它起作用了。万岁,为大家加油。
  • 查看更新的问题。问题半解决,但在 R 中揭示了超级奇怪的不合逻辑

标签: r if-statement nested match


【解决方案1】:

解决方案

调整您的示例使用:

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&lt;&lt;-grids 时,我们会得到一个错误,因为grids 没有被赋值,所以我们不能给@987654338 赋值@。

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,而不是那里没有存储任何东西。

这里的要点是,当您在函数中声明参数时,每次使用该函数时都会创建它们。它们存在。但是,如果您不在函数调用中为它们分配值,那么它们将存在,但没有任何价值。然后当你尝试使用它们时,它们缺少值会引发错误。

【讨论】:

  • 嗨,JC,感谢您的回答。我将研究字符串元素。我的问题是相反的:正在评估 2 并且代码正在达到“停止(等)”,即使它不应该是,因为网格不存在(作为对象或字符串)。但我会尝试将网格视为一个......对象,我猜?通过删除引号。
  • 没有引号,我得到:“存在错误(网格):找不到对象'网格'”。这就是我想要的......但是错误破坏了代码!
  • 好的,我查看了 exists 函数,它确实需要是一个字符串,所以将其保留为“网格”。我唯一能想到的是,这是在函数内部。您是否还有一个名为网格的全局变量(不在函数内部)。如果你这样做了,那么这个语句将评估那个变量。
  • 你好。如果我有一个名为 grids 的全局变量并在函数调用中调用它,那么它应该被评估,这是正确的行为。但是,如果我在全局范围内没有,exists("grids") 应该评估 FALSE 而不是继续表达......它正在做的事情。经过几个小时的调试,我更新了这个问题,以揭示一个不太可能且令人困惑的结果。
  • 嗨,J,是的。我一直在使用 if(grids!="NULL"),但你的更整洁。如果有人知道为什么会出现这个问题,我仍然会非常感兴趣......
【解决方案2】:
> 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 不存在时,表达式不会按预期计算。在测试您的第一个表达式之前,通过在控制台中运行 rm(grids) 确保 grids 不存在。

【讨论】:

  • 感谢全科医生。不幸的是,网格绝对不存在。正如我所说,运行 "if(exists("grids")) print("yay")" 不出所料。
  • “网格”是否存在于函数的环境中,还是存在于环境之外?您是否在同一个函数中运行两行代码?
  • 这两行都在函数中使用。从函数的变量列表中删除“网格”可以解决这个问题......有点。在对此进行了广泛的研究后,我正在更新这个问题。
  • 如果 grids 是函数的参数,为什么不将其默认值设置为 NA 或 null 而不是检查 grids 是否存在,而是检查它是否为 null 或 @ 987654328@?
  • 嗨,G,我现在已经根据自己的推论和 JCollerton 的建议做到了这一点。不过,我仍然对为什么会以这种方式出错感到困惑......
【解决方案3】:

Richard Scriven 的评论让我想到:grids 是我函数中的一个参数,但它是可选的,所以也许不应该指定(就像“...”可选函数中的任何内容一样)。我把它注释掉了,它起作用了。万岁,为大家加油。

【讨论】:

  • 编辑:要是这么简单就好了。查看更新的问题。
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 2019-08-21
  • 2019-03-16
  • 2015-02-22
  • 1970-01-01
  • 2014-12-08
  • 2011-01-27
  • 1970-01-01
相关资源
最近更新 更多