Warnings, Errors, and Getting Help

Reading

  • Bryan (2020)
  • “R Faq - How to Make a Great R Reproducible Example” (n.d.)
  • Wickham (2019)

Dependencies

install.packages("lubridate", "reprex")

Messages, warnings, and errors

Message
Things are fine, but here’s some information you should know
Warning
Uhhhh I’m gonna keep going, but maybe this isn’t what you want
Error
Nope. I’m stopping here. You need to fix the thing.
message('Hey, just FYI')
Hey, just FYI
warning('Uhhhh might want to check this out')
Warning: Uhhhh might want to check this out
stop('Noooooo')
Error in eval(expr, envir, enclos): Noooooo

Example: Dates are often problems

library(lubridate)

Attaching package: 'lubridate'
The following objects are masked from 'package:base':

    date, intersect, setdiff, union
add_six_months = function(date_str) {
    parsed_dates = parse_date_time(date_str, orders = 'mdY')
    parsed_dates %m+% months(6) 
}

some_data = c('June 2002', 'May 15, 2007', 'August 2007')
add_six_months(some_data)
Warning: 2 failed to parse.
[1] NA               "2007-11-15 UTC" NA              

Warning: This is a warning, not an error

  • R won’t stop running here
  • Errors might not show up until much later in our code, making it hard to identify the root cause
  • Or they might cause invisible problems, eg, by default lm() silently drops observations with missing values

A debugging mindset

“A debugging manifesto,” Julia Evans, https://jvns.ca/blog/2022/12/08/a-debugging-manifesto/
  1. Inspect, don’t squash
  2. Being stuck is temporary
  3. Trust nobody and nothing
  4. It’s probably your code
  5. Don’t go it alone
  6. There’s always a reason
  7. Build your toolkit
  8. It can be an adventure

Some debugging tactics

Debugging

some_data = c('June 2002', 'May 15, 2007', 'August 2007')
add_six_months(some_data)
Warning: 2 failed to parse.
[1] NA               "2007-11-15 UTC" NA              

Let’s start by using the RStudio debugger to isolate the problem

debugonce(add_six_months)
add_six_months(some_data)
debugging in: add_six_months(some_data)
debug at <text>#3: {
    parsed_dates = parse_date_time(date_str, orders = "mdY")
    parsed_dates %m+% months(6)
}
debug at <text>#4: parsed_dates = parse_date_time(date_str, orders = "mdY")
Warning: 2 failed to parse.
debug at <text>#5: parsed_dates %m+% months(6)
exiting from: add_six_months(some_data)
[1] NA               "2007-11-15 UTC" NA              

  • The problem is in lubridate::parse_date_time().
?parse_date_time
  • Spend a few minutes reading the documentation for this function and playing around with the call.


  • What does the argument orders do?
parse_date_time(some_data, orders = 'mdY')
Warning: 2 failed to parse.
[1] NA               "2007-05-15 UTC" NA              



parse_date_time(some_data, orders = c('mY', 'mdY'))
[1] "2002-06-01 UTC" "2007-05-15 UTC" "2007-08-01 UTC"


  • Make this change in add_six_months()
  • Confirm it no longer trips the assertion
  • Explain to your partner why this fixed things

Another example: More fun with dates

more_data = c('May 7, 2017', 'May 19, 2017', 'May Fifth, 2017')
mdy(more_data)
[1] "2017-05-07" "2017-05-19" "2017-05-20"

Screenshot of lubridate on CRAN, highlighting the BugReports field

Screenshot of lubridate issues page, showing a relevant search result (August 2021)

This is a known bug; it looks like they’re thinking about doing something about it, but the only workaround is to create an NA: https://github.com/tidyverse/lubridate/issues/685

Writing a reproducible example: reprex

Do not do these things in your reprex (or anywhere else)

Or Jenny Bryan will come to your office and set your computer on fire.

  • setwd('/users/danhicks/projects/catsaregreat/myscript/')
    • Used to ensure that R is running where your file is
    • Unnecessary if you’re opening different projects in different RStudio sessions
    • Will cause irrelevant errors on any other system
    • Instead, use file.path() or here::here() to build paths
  • rm(list=ls())
    • Used because people think it clears out the global environment
    • Doesn’t actually clear out the global environment
      • eg, doesn’t unload packages or reset options()
    • Unnecessary if you’re regularly using Session \(\to\) Restart R
    • Also unnecessary at the top of a Rmd file, which is always knit in a new session

Not on Bryan’s list, but also don’t do it:

  • require(package)
    • If package is installed, will act just like library()
    • If not, will return FALSE
      • The script will keep going until there’s an error about a missing function 300 lines later
      • Probably not the error you wanted help with
      • Annoying to debug because I have no idea where the function is supposed to come from
    • If library() can’t find the package, it immediately raises an error
      • I can tell right away what package needs to be installed

Labs

Lab 2 introduces you to some of RStudio’s debugging tools.

Lab 3 explores functional programming in R:

  • Assembling pipes using tidyverse functions
  • Writing code that respects immutability
  • Using the map() functional to apply a function to each element of a list
  • Writing a function factory to change the way a function behaves

References