Selective suppressWarnings() that filters by regul

2019-06-21 11:15发布

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?

标签: r warnings
2条回答
太酷不给撩
2楼-- · 2019-06-21 11:46

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
查看更多
We Are One
3楼-- · 2019-06-21 12:01

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.

查看更多
登录 后发表回答