Conditions: Errors, Warnings & Debugging
RStudio/Positron: breakpoints (click the gutter), step through, inspect environment.
24.1 Signaling conditions
stop("Something went wrong: ", x) # error
warning("This looks suspicious") # warning
message("Progress: 50%") # message (to stderr)
signalCondition(cond)
rlang::abort("Invalid input", class = "my_error", data = x) # classed conditions
cli::cli_abort("Column {.var {col}} not found") # formatted messages24.2 Handling conditions
result <- tryCatch(
{
log(-1)
},
warning = function(w) { message("Warning caught: ", conditionMessage(w)); NA },
error = function(e) { message("Error caught: ", conditionMessage(e)); NULL },
finally = { message("Cleanup") }
)
try(log("a"), silent = TRUE) # returns a "try-error" object
inherits(res, "try-error")
suppressWarnings(as.numeric("x")); suppressMessages(library(dplyr))
withCallingHandlers( # handle and continue
{ warning("w1"); "done" },
warning = function(w) { message("logged: ", conditionMessage(w)); invokeRestart("muffleWarning") }
)
on.exit(close(con), add = TRUE) # cleanup in functions24.3 Custom condition classes
my_condition <- function(msg, class) structure(class = c(class, "condition"), list(message = msg, call = sys.call(-1)))
tryCatch(stop(my_condition("bad value", c("value_error", "error"))),
value_error = function(e) "handled value error")24.4 Debugging tools
RStudio/Positron: breakpoints (click the gutter), step through, inspect environment. Use print()/str()/message() and reprex::reprex() to create minimal reproducible examples when asking for help.
traceback() # call stack after an error
browser() # pause execution inside a function (n, s, c, f, Q commands)
debug(myfun); undebug(myfun); debugonce(myfun)
options(error = recover) # choose a frame to inspect after an error
trace(myfun, browser, at = 3)
rlang::last_trace() # rich backtraces for rlang/tidyverse errors24.5 Defensive programming
stopifnot(is.data.frame(df), nrow(df) > 0)
checkmate::assert_number(x, lower = 0)
rlang::check_required(x)
vctrs::vec_assert(x, numeric())🧪 Part II Exercises
Create a 4×4 matrix of random integers; compute row/column means, its transpose, inverse (if possible), and eigenvalues.
Build a nested list describing a book (title, authors, chapters with page counts) and compute total pages with sapply.
Using penguins, compute mean bill length by species and sex with base R (aggregate) and with dplyr.
Clean a messy string vector: trim, lowercase, remove punctuation, extract numbers with stringr.
Parse a vector of dates in mixed formats with lubridate and compute each one's weekday and age in days.
Read a CSV with readr, fix column types, handle missing values, and write it to Parquet.
Reshape the billboard dataset (tidyr) from wide to long and plot rank over weeks for the top 5 songs.
Fit a linear model per species with nest() + purrr::map() and extract the slopes.
Recreate a publication-quality ggplot with facets, custom colors, labels, and theme; save at 300 dpi.
Write a function that downloads a file and retries up to 3 times using tryCatch, reporting warnings with withCallingHandlers.