Question

How can warning messages be saved in a vector or data frame within a loop so that they can be associated with a specific iteration?

Here's a toy example where I would like to store results and warning message (if any) from an operation (log(k)) in a data frame alongside the data (k):

dat <- data.frame(k=c(3,5,-2,7), logk=NA, warnMsg=NA)
for(i in 1:nrow(dat)){
  w <- length(warnings())
  dat$logk[i] <- log(dat$k[i])
  #if new warning, assign to data frame
  if(length(warnings()) > length (w)){
     dat$warnMsg[i] <- warnings()[length(warnings())]
  }
}

It seems this doesn't work because any warnings that are generated within the loop are not available to the warnings() call until the loop is over. Do I need to specify a different environment to access new warnings within the loop?

I suspect there is also a better way to do this altogether using try() or tryCatch() but it isn't obvious to me yet.

Was it helpful?

Solution

You can accomplish what you want with the withCallingHandlers function, like so

withCallingHandlers({
    for(i in 1:nrow(dat)){
        w <- length(warnings())
        dat$logk[i] <- log(dat$k[i])
    }
}, warning = function(w){
    dat$warnMsg[i] <<- w$message
    invokeRestart("muffleWarning")
})

Notice that you need the <<- operator in the warning handler to assign the message to the data frame in the global environment, since <- would create a local copy of dat within the handler and discard it upon exit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top