Selective suppressWarnings() that filters by regular expression
Asked Answered
T

2

9

In an attempt to generate code that runs without warnings and hence can be run with options(warn=2), I am looking for an implementation of the suppressWarnings routine that would only filter warnings that match a given (vector of) regular expressions. Some warnings are just beyond my control, like the famous

Unrecognized record type 7, subtype 18 encountered in system file

when reading certain SPSS files, and I want to selectively suppress these without affecting possible other warnings.

Is there already an implementation of this functionality?

Transform answered 13/5, 2013 at 8:33 Comment(3)
How about wrapping your functions in tryCatch? That way you can catch warnings and filter accordingly.Allomorphism
when I raised this sort of thing on the r development list (I think) I was warned that this approach might fail in a non-English locale, where the text of the warning messages would be different.Karafuto
@BenBolker: Good catch. Found your message: stat.ethz.ch/pipermail/r-devel/2012-October/065060.html. I haven't yet followed the entire discussion, but I think that a false negative (=a message that should have been warned about but isn't because it translates to an ignored message) is highly unlikely. We can easily cope with false positives: Simply add a regular expression that filters for the translated variant.Transform
C
10

Suppress warnings with withCallingHandlers and invokeRestart, using the "muffleWarning" restart mentioned on ?warning

withCallingHandlers({
    x <- 0
    warning("Unrecognized record 123")
    x <- x + 1
    warning("another warning")
    x + 1
}, warning = function(w) {
    if (startsWith(conditionMessage(w), "Unrecognized record"))
        invokeRestart("muffleWarning")
})

This has the output

[1] 2
Warning message:
In withCallingHandlers({ : another warning

(use tryCatch if instead you would like to stop on warning). As @BenBolker mentions this doesn't handle translations; making a more elaborate regex isn't going to be satisfactory. For catching one's own warnings, one could make and throw a subclass of warning.

Chalcis answered 13/5, 2013 at 11:34 Comment(0)
B
7

I wrote a wrapper around @martin-morgan's answer for convenience, it works like SuppressWarnings except that you can pass a regular expression to the second argument (which will be passed to grepl) or a function that will be applied to the error message, using the dots as additional arguments.

I made it support the formula notation.

See examples below.

suppress_warnings <- function(.expr, .f, ...) {
  eval.parent(substitute(
  withCallingHandlers( .expr, warning = function(w) {
    cm <- conditionMessage(w)
    cond <- 
      if(is.character(.f)) grepl(.f, cm) else rlang::as_function(.f)(cm,...)
    if (cond) {
      invokeRestart("muffleWarning")
    }
  })
  ))
}


suppress_warnings({sqrt(-1); warning("ooops", call. = FALSE)}, startsWith, "o")
# Warning message:
# In sqrt(-1) : NaNs produced
suppress_warnings({sqrt(-1); warning("ooops", call. = FALSE)}, ~nchar(.)>10)
# Warning message:
# ooops
suppress_warnings({sqrt(-1); warning("ooops", call. = FALSE)}, "NaN")
# Warning message:
# ooops
Broderickbrodeur answered 15/3, 2019 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.