【问题标题】:How can I check whether a function call results in a warning?如何检查函数调用是否导致警告?
【发布时间】:2011-04-23 14:55:09
【问题描述】:

在 R 中,如何确定函数调用是否导致警告?

也就是说,在调用该函数之后,我想知道该调用的实例是否产生了警告。

【问题讨论】:

标签: r


【解决方案1】:

如果您想使用try 构造,您可以设置警告选项。另见?options。更好的是使用tryCatch()

x <- function(i){
  if (i < 10) warning("A warning")
  i
}

tt <- tryCatch(x(5),error=function(e) e, warning=function(w) w)

tt2 <- tryCatch(x(15),error=function(e) e, warning=function(w) w)

tt
## <simpleWarning in x(5): A warning>

tt2
## [1] 15

if(is(tt,"warning")) print("KOOKOO")
## [1] "KOOKOO"

if(is(tt2,"warning")) print("KOOKOO")

同时获得结果和警告:

tryCatch(x(5),warning=function(w) return(list(x(5),w)))

## [[1]]
## [1] 5
## 
## [[2]]
## <simpleWarning in x(5): A warning>

使用try

op <- options(warn=2)

tt <- try(x())
ifelse(is(tt,"try-error"),"There was a warning or an error","OK")
options(op)

【讨论】:

  • 感谢您的编辑显示如何获得结果和警告;但是,当出现警告时,该函数会被调用两次。是否可以只调用一次(例如,如果函数很慢)?
  • @Aaron :那么我会选择处理程序,如下所示。这是最干净的方式,而那些就是这样做的。它只是需要更多的令人费解。
  • 谢谢。这绝对是令人费解的。虽然它可以满足我的需要,但代码中有很多我不明白的地方。
【解决方案2】:

在 R-help 邮件列表(请参阅 http://tolstoy.newcastle.edu.au/R/help/04/06/0217.html)上,Luke Tierney 写道:

"如果你想写一个计算一个值并收集所有 警告你可以这样做:

withWarnings <- function(expr) {
    myWarnings <- NULL
    wHandler <- function(w) {
        myWarnings <<- c(myWarnings, list(w))
        invokeRestart("muffleWarning")
    }
    val <- withCallingHandlers(expr, warning = wHandler)
    list(value = val, warnings = myWarnings)
} 

【讨论】:

  • 是的,这样它会更新函数外的myWarnings;否则它会在函数内部创建一个新的myWarnings,而外部的不会更新。
【解决方案3】:

这是一个例子:

testit <- function() warning("testit") # function that generates warning.

assign("last.warning", NULL, envir = baseenv()) # clear the previous warning

testit() # run it

if(length(warnings())>0){ # or !is.null(warnings())
    print("something happened")
}

也许这是间接的,但我不知道更直接的方法。

【讨论】:

  • 虽然这很不优雅,但这很好,因为我找不到任何其他方法来捕获警告并从函数返回正常结果。也就是说,如果 testit() 返回一个值,使用 tryExcept 捕获警告意味着您丢失了该值。除非我错过了什么?
  • @Alex :您可以使用 tryCatch 公式轻松完成。你可以对参数中的警告做一些事情,例如:warning=function(w) {...do something ... return(normal result)}
  • @Joris:我无法让 tryCatch 返回正常结果。我错过了什么吗?我确实从 R 邮件列表(作为单独的答案包含在内)中找到了使用 withCallingHandlers 的方法。
  • @AlexHolcombe 您还可以设置options(warn=1),在这种情况下,警告将打印到stdout,而不是stderr
【解决方案4】:

2019 年更新

您可以使用 purrr 包中的“安静地”,它返回输出、结果、警告和错误的列表。然后,您可以按名称提取每个元素。例如,如果您有一个列表,您想在其上映射一个函数,并找到返回警告的元素,您可以这样做

library(purrr)
library(lubridate)

datelist <- list(a = "12/12/2002", b = "12-12-2003", c = "24-03-2005")

# get all the everything
quiet_list <- map(datelist, quietly(mdy))

# find the elements which produced warnings
quiet_list %>% map("warnings") %>% keep(~ !is.null(.))

# or 
quiet_list %>% keep(~ length(.$warnings) != 0)

对于这个例子来说,这是非常简单的,但是对于可能难以发现 NA 的一长串数据帧,这非常有用。

【讨论】:

    【解决方案5】:

    对于一个简单的TRUE/FALSE 返回给定操作是否导致警告(或错误),您可以使用berryFunctions package 中的is.error 函数,在第一次设置@987654326 之后@ 以便将警告转换为错误。

    例如,

    options(warn = 2)
    berryFunctions::is.error(as.numeric("x")) # TRUE
    berryFunctions::is.error(as.numeric("3")) # FALSE
    

    如果您想将选项更改限制为使用此功能,您可以创建一个新功能,如下所示。

    is.warningorerror <- function(x) {
     op <- options()
     on.exit(options(op))
     options(warn = 2)
     berryFunctions::is.error(x)
    }
    
    is.warningorerror(as.numeric("x")) # TRUE
    options("warn") # still 0 (default)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      • 2017-12-20
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多