R:尽管条件为 FALSE,IF 语句仍评估表达式?
R: IF statement evaluating expression despite condition being FALSE?
我在 R 中有一个很大的函数,用户可以不 include/specify 一个对象。如果是,代码会检查以确保该对象中的名称与另一个对象中的名称相匹配。如果他们不这样做,则无需进行该检查。代码行是:
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 语句?我应该在第二个大括号周围加上另一组大括号吗??
谢谢!
编辑:更多问题。从变量的函数列表中删除 "grids," 意味着如果没有名为 grids 的对象并且您没有在调用中指定它(即 function(x,grids=whatever)
),它就可以工作。在函数变量列表中保留 "grids," 意味着如果有一个名为 grids 的对象并且您在调用中指定它,它就可以工作。
请看这个:http://i.imgur.com/9mr1Lwi.png
使用 exists(grids)
已经过时了,因为 exists 需要 "quotes" 并且没有 em 一切都会失败。有了它们 ("grids"),我需要决定是否将 "grids," 保留在函数列表中。如果我不这样做,但我在调用 (function(x,grids=whatever))
中指定了它,那么我会得到未使用的参数失败。如果我这样做了,但没有在调用中指定它,因为网格不存在并且我不想使用它,我会得到匹配错误,网格没有默认值。
我该如何解决这个问题?也许在函数变量列表中将其列为 grids="NULL"
,然后而不是 if(exists("grids"))
做 if(grids!="NULL")
我仍然不知道为什么会出现原来的匹配问题。匹配来自 expvarnames/grids 名称检查器,它位于 if(exists("grids"))
之后,计算结果为 FALSE。 WAaaaaaaiiiittttt..... 如果我在函数变量列表中指定网格,即简单地放置 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)
所以在第一个例子中,函数似乎创建了一个名为 "grids" 的对象,因为 exists("grids") 的计算结果为真。但是然后,在同一条线上,当被要求对网格做些什么时,它说它不存在!薛定谔的对象?!
这在示例 2 中得到了证明:grids 评估为 true 并且 a 被全局分配,然后该函数执行其操作。疯狂。完全疯狂。有谁知道为什么会发生这种荒谬的事情?在函数变量列表中使用我的 grids="NULL" default 是最好的解决方案吗?
谢谢。
可重现的例子,如果你愿意,但我已经为每个排列完成了:
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")
解决方案
调整您的示例使用:
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)
将 return 什么都没有。通过在函数中将默认参数指定为 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
,而不是那里没有存储任何内容。
要点在于,当您在函数中声明参数时,每次使用该函数时都会创建它们。它们存在。但是,如果您不在函数调用中为它们分配值,那么它们将存在,但没有任何价值。然后,当您尝试使用它们时,它们缺少值会引发错误。
> 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
。
Richard Scriven 的评论让我开始思考:grids 是我函数中的一个参数,但它是可选的,因此可能不应该指定(就像“...”可选函数中的任何内容)。我把它注释掉了,它起作用了。万岁,大家加油。
我在 R 中有一个很大的函数,用户可以不 include/specify 一个对象。如果是,代码会检查以确保该对象中的名称与另一个对象中的名称相匹配。如果他们不这样做,则无需进行该检查。代码行是:
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 语句?我应该在第二个大括号周围加上另一组大括号吗??
谢谢!
编辑:更多问题。从变量的函数列表中删除 "grids," 意味着如果没有名为 grids 的对象并且您没有在调用中指定它(即 function(x,grids=whatever)
),它就可以工作。在函数变量列表中保留 "grids," 意味着如果有一个名为 grids 的对象并且您在调用中指定它,它就可以工作。
请看这个:http://i.imgur.com/9mr1Lwi.png
使用 exists(grids)
已经过时了,因为 exists 需要 "quotes" 并且没有 em 一切都会失败。有了它们 ("grids"),我需要决定是否将 "grids," 保留在函数列表中。如果我不这样做,但我在调用 (function(x,grids=whatever))
中指定了它,那么我会得到未使用的参数失败。如果我这样做了,但没有在调用中指定它,因为网格不存在并且我不想使用它,我会得到匹配错误,网格没有默认值。
我该如何解决这个问题?也许在函数变量列表中将其列为 grids="NULL"
,然后而不是 if(exists("grids"))
做 if(grids!="NULL")
我仍然不知道为什么会出现原来的匹配问题。匹配来自 expvarnames/grids 名称检查器,它位于 if(exists("grids"))
之后,计算结果为 FALSE。 WAaaaaaaiiiittttt..... 如果我在函数变量列表中指定网格,即简单地放置 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)
所以在第一个例子中,函数似乎创建了一个名为 "grids" 的对象,因为 exists("grids") 的计算结果为真。但是然后,在同一条线上,当被要求对网格做些什么时,它说它不存在!薛定谔的对象?! 这在示例 2 中得到了证明:grids 评估为 true 并且 a 被全局分配,然后该函数执行其操作。疯狂。完全疯狂。有谁知道为什么会发生这种荒谬的事情?在函数变量列表中使用我的 grids="NULL" default 是最好的解决方案吗? 谢谢。
可重现的例子,如果你愿意,但我已经为每个排列完成了:
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")
解决方案
调整您的示例使用:
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)
将 return 什么都没有。通过在函数中将默认参数指定为 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
,而不是那里没有存储任何内容。
要点在于,当您在函数中声明参数时,每次使用该函数时都会创建它们。它们存在。但是,如果您不在函数调用中为它们分配值,那么它们将存在,但没有任何价值。然后,当您尝试使用它们时,它们缺少值会引发错误。
> 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
。
Richard Scriven 的评论让我开始思考:grids 是我函数中的一个参数,但它是可选的,因此可能不应该指定(就像“...”可选函数中的任何内容)。我把它注释掉了,它起作用了。万岁,大家加油。