Error and Exception Handling
Why Learn Error Handling in Data Analytics?
Imagine you are developing a batch data importer that downloads and parses 100 CSV sales files from different servers.
If one of the files is corrupted or missing, a standard R script will hit an error and stop immediately. If this happens at file 50, your program crashes, and you lose all the data you spent the last hour loading!
You want R to do this:
- Try to read the file.
- If an error occurs, print a warning like
"Warning: File 50 missing, skipping...", and continue loading the remaining 50 files.
In R, we manage this using tryCatch(). It allows you to build robust, crash-resistant data pipelines.
1. R's Error Concept: Conditions
R refers to unexpected execution events as conditions. There are three main types:
- Errors: Unrecoverable problems. The script halts immediately unless caught.
- Warnings: Minor issues. R alerts you, but the script continues running (e.g., coercion warnings).
- Messages: Helpful info prints. They do not disrupt the script.
2. The tryCatch() Structure
To catch errors and warnings, wrap your code inside a tryCatch() function:
Syntax
result <- tryCatch({
# Risky code here
}, error = function(err) {
# Code to run if an error occurs
# 'err' holds the error message
}, warning = function(war) {
# Code to run if a warning occurs
}, finally = {
# Code to run no matter what (clean up connections, files)
})
3. Division by Zero in R: A Surprise!
In Python, dividing by zero (10 / 0) throws a ZeroDivisionError and crashes the program.
In R, dividing a number by zero does not throw an error! R is a statistical language, so it returns mathematical concepts:
10 / 0returnsInf(Infinity).-10 / 0returns-Inf(Negative Infinity).0 / 0returnsNaN(Not a Number).
# Division by zero in R does NOT trigger the error handler!
result <- 10 / 0
print(result) # Inf
4. Throwing Custom Errors: stop() and warning()
To halt a function and throw a custom error, use stop(). To trigger a warning without halting, use warning():
check_ratio <- function(ratio) {
if (ratio < 0) {
stop("Error: Ratio cannot be negative!")
}
return(ratio * 100)
}
# Catching the stop() call
tryCatch({
check_ratio(-0.5)
}, error = function(e) {
print(paste("Caught error:", e$message))
})
Hands-on Exercises
Exercise 1: Safe Log Calculator
In mathematics, taking the logarithm of a negative number is undefined. In R, log(-5) returns NaN and prints a warning. Let's write a function that safely handles this warning.
Write R code to:
- Wrap
log(-5)in atryCatch()block. - In the
warninghandler, print a friendly message:"Warning caught: Input must be positive. Returning 0."and return0. - Save the result of
tryCatch()into a variableresultand print it.
# Write your code below and click Run Code
Click to view Answer
result <- tryCatch({
log(-5)
}, warning = function(w) {
print("Warning caught: Input must be positive. Returning 0.")
return(0)
})
print(result) # Output: 0
Exercise 2: Database Connection Cleanup
When working with database connections, we must close the connection even if our calculations fail midway. Write R code to:
- Define a variable
db_open <- TRUE. - Inside
tryCatch(), write a block that throws an error usingstop("Database query timed out!"). - In the
finallyblock, setdb_open <- FALSEand print"Connection closed." - Confirm
db_openisFALSEafter thetryCatch()block completes.
# Write your code below and click Run Code
Click to view Answer
db_open <- TRUE
tryCatch({
print("Running query...")
stop("Database query timed out!")
}, error = function(e) {
print(paste("Query failed:", e$message))
}, finally = {
db_open <- FALSE
print("Connection closed.")
})
print(paste("Is database open?", db_open)) # Should print FALSE