One function I use can return warnings: the 1st warning is always happening and I don't care about it. The following warnings are usually of interest because they actually warn that something really go wrong.
Here is an example of the usual warning returned by my function that I don't care about:
Warning message:
Using alpha for a discrete variable is not advised.
Here is now an example of the usual warning + a relevant warning that I actually would like to see when it happens to be returned:
Warning messages:
1: Using alpha for a discrete variable is not advised.
2: Removed 2 rows containing missing values (geom_point).
My question is how can I suppress the 1st warning (Using alpha for a discrete variable is not advised.
), either based on its position in the warnings list, or using a regular expression...or any other idea, without using other packages than the default R ones (base, datasets, graphics, stats...) ?
So far the solution I found makes use of the package pkgcond v0.1.0 which has its own suppress_warnings() function. But I really want to avoid loading additional packages.
Thank you in advance for your help!
Here is one way to handle the problem, and it is all in base R.
Let's start with a function that returns a value we want but will throw two warnings before doing so:
make_warnings <- function()
{
warning("This is a warning that can be ignored")
warning("This is a warning that shouldn't be ignored")
return(0)
}
Of course, if we run this, we will get warnings:
make_warnings()
#> [1] 0
#> Warning messages:
#> 1: In make_warnings() : This is a warning that can be ignored
#> 2: In make_warnings() : This is a warning that shouldn't be ignored
If we run the function inside suppressWarnings
we just lose all the warnings and that's not what we want. But we can use withCallingHandlers
, which provides a warning
parameter that allows us to specify a function that takes each warning generated and does whatever we like programatically with it.
All we need to do is set up a function that checks the contents of each warning using a regular expression with grepl
and suppresses that warning if it matches our regex.
Note that this function will be called once for each warning caught inside withCallingHandlers
. We don't even need to specify what will happen to uncaught warnings, because if they aren't specifically suppressed in our function, they will still generate a warning to the console:
warning_handler <- function(w)
{
condition <- conditionMessage(w)
if(grepl("can be ignored", condition)) invokeRestart("muffleWarning")
}
So now we can run our warning-producing function and just silence the warnings we don't care about.
withCallingHandlers(make_warnings(), warning = warning_handler)
#> [1] 0
#> Warning message:
#> In make_warnings() : This is a warning that shouldn't be ignored
So you can see we have suppressed the warning we didn't want to see but kept the important one.
If you want to make this more flexible, you can wrap withCallingHandlers
and your handling function into a single function that takes the regex as the first argument:
with_warning_handler <- function(reg, ...)
{
withCallingHandlers(..., warning = function(w)
{
condition <- conditionMessage(w)
if(grepl(reg, condition)) invokeRestart("muffleWarning")
})
}
So now you can do things like this:
with_warning_handler("can be ignored", make_warnings())
#> [1] 0
#> Warning message:
#> In make_warnings() : This is a warning that shouldn't be ignored
So, looking at a real-world example, look at the two warnings we get with this line of code:
a <- 1:3; a[] <- as.numeric(c("A", "1"))
#> Warning messages:
#> 1: NAs introduced by coercion
#> 2: In a[] <- as.numeric(c("A", "1")) :
#> number of items to replace is not a multiple of replacement length
But if we're not worried about the coercion, we can do:
with_warning_handler("coercion", {a <- 1:3; a[] <- as.numeric(c("A", "1"))})
#> Warning message:
#> In a[] <- as.numeric(c("A", "1")) :
#> number of items to replace is not a multiple of replacement length