How can I check whether a function call results in a warning?

Solution 1:

If you want to use the try constructs, you can set the options for warn. See also ?options. Better is to use 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")

To get both the result and the warning :

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

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

Using try

op <- options(warn=2)

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

Solution 2:

On the R-help mailing list (see http://tolstoy.newcastle.edu.au/R/help/04/06/0217.html), Luke Tierney wrote:

"If you want to write a function that computes a value and collects all warning you could do it like this:

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

Solution 3:

here is an example:

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

maybe this is somehow indirect, but i don't know the more straightforward way.

Solution 4:

2019 update

You can you use 'quietly' from the purrr package, which returns a list of output, result, warning and error. You can then extract each element by name. For instance, if you had a list, which you want to map a function over, and find the elements which returned a warning you could do

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)

For this example it's quite trivial, but for a long list of dataframes where the NAs might be hard to spot, this is quite useful.