Search code examples
rr-markdownwarningsknitr

How to control R warnings in knitr to rmarkdown


I have a chunk with a loop which produces images and results of a linear model. Sometimes the model produces non-convergence warnings. Images and results become fully disorganised if I let warning=TRUE as chunk condition. But I want to print the warning, so I try it through cat(names(last.warning)) (thanks to this SO). Then I get the next error when knitr:

Error in eval(expr, envir, enclos) : object 'last.warning' not found
Calls: <Anonymous> ... handle -> withCallingHandlers -> withVisible -> eval -> eval

Execution halted

What can I do?

Thank you!


Solution

  • The idea is to try to catch the warning and print its message. The following example is inside a suppressWarnings call, which should have the same effect as being inside a warning = FALSE chunk.

    Here the actual code I want to run is just as.numeric(c("1", "A")). I want to print any warnings the code generates despite it being inside a suppressWarnings block, and I also want to print the result of the code:

    suppressWarnings({
    
    #--- Code chunk ----------------------------------------------------------#  
      
      withCallingHandlers(
            expr    = as.numeric(c("1", "A")), 
            warning = function(w) cat("** warning:", w$message, "**\n\n")
      )
    
    #--- End of code chunk ---------------------------------------------------#
    
    })
    
    #> ** warning: NAs introduced by coercion **
    #> 
    #> [1]  1 NA
    

    Edit

    Here is a reproducible Rmd that shows how to display any warnings optionally after the result of the calculation is printed:

    ---
    title: "test"
    author: "Allan Cameron"
    date: "27 November 2020"
    output: html_document
    ---
    
    ```{r setup, include=FALSE, warning=FALSE}
    knitr::opts_chunk$set(echo = TRUE)
     ```
    
     ## Print warning after output
    
     ```{r test, warning=FALSE}
       withCallingHandlers(
            expr    = as.numeric(c("1", "A")), 
            warning = function(w) warn <<- paste("** warning:", w$message, "**\n\n")
       )
    ```
    
    ```{r print_warn, echo=FALSE}
      if(exists("warn")) cat(warn)
    ```
    

    This produces:

    enter image description here