0

My question is similar to this one but that returns the error, and this one which has no answers. I want to catch errors (returning NA) and warnings (returning NaN) but saving the warning message for later analysis. The result gives the desired values, but my list of warnings doesn't capture the warnings.

MWE:

# Dummy data
data <- tibble(c(5, 6), c("a", NA_real_), c(NA_real_, NA_real_))

# Initialise output variables
result <- NULL
warnings <- vector("list", ncol(data))

for(i in 1:3){
    temp <- tryCatch(
        max(data[,i], na.rm = TRUE),
        error = function(e) NA,
        warning = function(w) {
            warnings[[i]] <- w   # Return this to `warnings`
            NaN                  # Return this to `result`
        }
    )
    result <- c(result, temp)
}

The desired output for warnings is an empty list except the third element should contain the warning along the lines of "no non-missing arguments to max; returning -Inf" (additional text is fine).

2
  • As a follow up, how can I return the original result, in this case -Inf from max(c(NA, NA), na.rm = TRUE) to result while returning the warning message to warnings (i.e. I don't want to hardcode the result of NaN Commented Oct 28 at 0:16
  • 1
    you could return structure(NaN, warning = w) instead. and you shouldn't "grow" objects like result <- c(result, temp) especially since you are mixing types. instead pre-allocate result like you did for warnings and use a list Commented Oct 28 at 2:58

2 Answers 2

2

You don't have to use <<-, you can return the warning and test it after.
In the code below I have also changed the error trapping code to return the error.

library(tibble)
# Dummy data
data <- tibble(c(5, 6), c("a", NA_real_), c(NA_real_, NA_real_))

# Initialise output variables
result <- numeric(ncol(data))
warnings <- vector("list", ncol(data))

for(i in 1:3){
  temp <- tryCatch(
    max(data[,i], na.rm = TRUE),
    error = function(e) e,
    warning = function(w) w
  )
  if(inherits(temp, "warning")) {
    warnings[[i]] <- conditionMessage(temp)
    temp <- NaN
  }
  if(inherits(temp, "error")) {
    warnings[[i]] <- conditionMessage(temp)
    temp <- NA
  }
  result[i] <- temp
}

result
#> [1]   6  NA NaN
warnings
#> [[1]]
#> NULL
#> 
#> [[2]]
#> [1] "only defined on a data frame with all numeric-alike variables"
#> 
#> [[3]]
#> [1] "no non-missing arguments to max; returning -Inf"

Created on 2025-10-28 with reprex v2.1.1


Edit

In the code that follows, I solve the problem the OP raises in comment

But how do I change the line temp <- NaN to instead return the original output of max(data[,i], na.rm = TRUE), in this case -Inf? So warnings would be the same, but result would look like c(6, NA, -Inf). Is there some other function like conditionMessage to get this?

with a function in this SO post.

#
# https://stackoverflow.com/a/32076859/8245406
#
tryCatch.W.E <- function(expr)
{
  W <- NULL
  w.handler <- function(w){ # warning handler
    W <<- w
    invokeRestart("muffleWarning")
  }
  list(value = withCallingHandlers(tryCatch(expr, error = function(e) e),
                                   warning = w.handler),
       warning = W)
}

library(tibble)
# Dummy data
data <- tibble(c(5, 6), c("a", NA_real_), c(NA_real_, NA_real_))

# Initialise output variables
result <- numeric(ncol(data))
warnings <- vector("list", ncol(data))

for(i in 1:ncol(data)){
  temp <- tryCatch.W.E(
    max(data[, i], na.rm = TRUE)
  )
  if(inherits(temp$warning, c("warning", "error"))) {
    warnings[[i]] <- conditionMessage(temp$warning)
  }
  if(inherits(temp$value, c("warning", "error"))) {
    warnings[[i]] <- conditionMessage(temp$value)
    result[i] <- NA  # or NaN
  } else result[i] <- temp$value
}

result
#> [1]    6   NA -Inf
warnings
#> [[1]]
#> NULL
#> 
#> [[2]]
#> [1] "only defined on a data frame with all numeric-alike variables"
#> 
#> [[3]]
#> [1] "no non-missing arguments to max; returning -Inf"

Created on 2025-10-29 with reprex v2.1.1

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this suggestion. This solves my initial question. But how do I change the line temp <- NaN to instead return the original output of max(data[,i], na.rm = TRUE), in this case -Inf? So warnings would be the same, but result would look like c(6, NA, -Inf). Is there some other function like conditionMessage to get this?
Done, see the edit.
0

And I just discovered the answer....

For some reason, the parent assignment operator <<- needs to be used here, e.g.

warnings[[i]] <<- w   # Return this to `warnings`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.