1

I'm running a lot of models and some throw errors. I want to save all outputs and all errors. However, my attemts with tryCatch coming from here led to a code which either returns the warning or, if there is no warning, returns and creates the object. Here is the code:

DT <- iris
str(DT)
DT$binary <- as.numeric(DT$Petal.Width>1)
DT$dummy <- as.numeric(as.numeric(DT$Species)>2)

a model with a warning returns the warning but does not retain the logit model in the environment:

test <- tryCatch(
logit1 <- glm(binary~Sepal.Length+dummy,data = DT, family = binomial( link = 'logit')),
warning = function( w ) { conditionMessage( w ) } )

a model without a warning creates the logit object in the environment but when I save this tryCatch as an object, it is the whole logit output.

test <- tryCatch(
logit2 <- glm(binary~Sepal.Length+Sepal.Width,data = DT, family = binomial( link = 'logit')),
warning = function( w ) { conditionMessage( w ) } )

as if tryCatch is not even there (which I guess makes sense as the condition is not fulfilled). I'm looking for code which gives me nothing, a 0, or NA if there is no warning but the warning message if there is a warning and which creates the named logit model no matter if there is a warning or not. Somehow, tryCatch does not seem to be very suitable for this, ideally, I'd just run the logit and save the warning message if that is possible?

Jakob
  • 1,325
  • 15
  • 31

1 Answers1

1

Here is some code that shows how to

  • intercept warnings and errors that are raised by a function, so that you can do whatever you want at that point (e.g. store the message), and
  • return the result of the function, if it did not raise an error, and return something else if it did raise an error.

This is not exactly what you wanted but you should be able to adapt it to solve your problem.

First here is a function that sometimes raises warnings and errors:

f <- function(x) {
    if (x %% 2 == 0) warning("warning number 1")
    if (x %% 3 == 0) warning("warning number 2")
    if (x %% 5 == 0) stop("error number 1")
    if (x %% 7 == 0) stop("error number 2")
    return(100)
}

Here is a function that wraps around f and intercepts any warnings and errors that it raises:

g <- function(x) {
    errorMessage <- character()
    warningMessages <- character()

    result <- withCallingHandlers(
            tryCatch(
                    f(x),
                    error = function(e) {
                        # Code here will be run if f raises an error. 
                        errorMessage <<- conditionMessage(e)
                        # To edit the error message and raise the error, use this:
                        # stop("some extra text\n", conditionMessage(e))
                        return(200)  # this will be assigned to result
                    }
            ), 
            warning = function(w) {
                # Code here will be run if f raises a warning. 
                warningMessages <<- append(warningMessages, conditionMessage(w))
                # To edit the warning message and raise the warning, use this:
                # warning("some extra text\n", conditionMessage(w))
                # The following line is needed at the end to transfer control
                # back to the appropriate place in f:
                invokeRestart("muffleWarning")
            }
    )

    if (length(warningMessages) > 0)
        cat("WARNINGS:\n", paste(warningMessages, collapse="\n"), "\n", sep="")
    if (length(errorMessage) > 0)
        cat("ERROR:\n", paste(errorMessage, collapse="\n"), "\n", sep="")
    return(result)
}

Here is what happens when there are no warnings or errors:

> g(11)
[1] 100

When there are warnings but no errors:

> g(6)
WARNINGS:
warning number 1
warning number 2
[1] 100

When there is an error:

> g(35)
ERROR:
error number 1
[1] 200

And when there are both warnings and errors:

> g(42)
WARNINGS:
warning number 1
warning number 2
ERROR:
error number 2
[1] 200

So there you are. As you can see, the code in g is not easy to understand. And things like invokeRestart("muffleWarnings") are not documented well.

user1310503
  • 557
  • 5
  • 11