Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

R Programming: Understanding Messages, Warnings, and Errors, Lecture notes of Advanced Computer Programming

An overview of different types of indications in R programming, including messages, warnings, and errors. It includes examples of each type and explains how to handle them. The document also covers the use of debugging tools such as traceback(), debug(), browser(), and recover() to diagnose and fix issues in R functions.

What you will learn

  • How can you handle messages, warnings, and errors in R programming?
  • What is the difference between a message, warning, and error in R programming?
  • What debugging tools are available in R and how can they be used to diagnose and fix issues in functions?

Typology: Lecture notes

2021/2022

Uploaded on 09/12/2022

ekaatma
ekaatma 🇺🇸

4.2

(34)

268 documents

1 / 9

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
pf3
pf4
pf5
pf8
pf9

Partial preview of the text

Download R Programming: Understanding Messages, Warnings, and Errors and more Lecture notes Advanced Computer Programming in PDF only on Docsity!

20. Debugging

20.1 Something’s Wrong!

Watch a video of this section¹ (note that this video differs slightly from the material presented here)

R has a number of ways to indicate to you that something’s not right. There are different levels of

indication that can be used, ranging from mere notification to fatal error. Executing any function in

R may result in the following conditions.

  • message: A generic notification/diagnostic message produced by the message() function;

execution of the function continues

  • warning: An indication that something is wrong but not necessarily fatal; execution of the

function continues. Warnings are generated by the warning() function

  • error: An indication that a fatal problem has occurred and execution of the function stops.

Errors are produced by the stop() function.

  • condition: A generic concept for indicating that something unexpected has occurred; pro-

grammers can create their own custom conditions if they want.

Here is an example of a warning that you might receive in the course of using R.

log (-1) Warning in log (-1): NaNs produced [ 1 ] NaN

This warning lets you know that taking the log of a negative number results in a NaN value because

you can’t take the log of negative numbers. Nevertheless, R doesn’t give an error, because it has a

useful value that it can return, the NaN value. The warning is just there to let you know that something

unexpected happen. Depending on what you are programming, you may have intentionally taken

the log of a negative number in order to move on to another section of code.

Here is another function that is designed to print a message to the console depending on the nature

of its input.

¹https://youtu.be/LHQxbRInyyc

printmessage2( NA ) [ 1 ] "x is a missing value!"

And all is fine.

Now what about the following situation.

x <- log ( c (-1, 2 )) Warning in log ( c (-1, 2 )): NaNs produced printmessage2(x) Warning in if ( is.na (x)) print ("x is a missing value!") else if (x > 0) print ("x is greater than zero") else print ("x is less than or equal to zero"): the condition has length > 1 and only the first element will be used [ 1 ] "x is a missing value!"

Now what?? Why are we getting this warning? The warning says “the condition has length > 1 and

only the first element will be used”.

The problem here is that I passed printmessage2() a vector x that was of length 2 rather then length

1. Inside the body of printmessage2() the expression is.na(x) returns a vector that is tested in the

if statement. However, if cannot take vector arguments so you get a warning. The fundamental

problem here is that printmessage2() is not vectorized.

We can solve this problem two ways. One is by simply not allowing vector arguments. The other

way is to vectorize the printmessage2() function to allow it to take vector arguments.

For the first way, we simply need to check the length of the input.

printmessage3 <- function (x) {

  • if ( length (x) > 1L)
  • stop ("'x' has length > 1")
  • if ( is.na (x))
  • print ("x is a missing value!")
  • else if (x > 0)
  • print ("x is greater than zero")
  • else
  • print ("x is less than or equal to zero")
  • invisible (x)
  • }

Now when we pass printmessage3() a vector we should get an error.

printmessage3(1:2) Error in printmessage3(1:2): 'x' has length > 1

Vectorizing the function can be accomplished easily with the Vectorize() function.

printmessage4 <- Vectorize (printmessage2) out <- printmessage4( c (-1, 2 )) [ 1 ] "x is less than or equal to zero" [ 1 ] "x is greater than zero"

You can see now that the correct messages are printed without any warning or error. Note that I

stored the return value of printmessage4() in a separate R object called out. This is because when

I use the Vectorize() function it no longer preserves the invisibility of the return value.

20.2 Figuring Out What’s Wrong

The primary task of debugging any R code is correctly diagnosing what the problem is. When

diagnosing a problem with your code (or somebody else’s), it’s important first understand what

you were expecting to occur. Then you need to idenfity what did occur and how did it deviate from

your expectations. Some basic questions you need to ask are

  • What was your input? How did you call the function?
  • What were you expecting? Output, messages, other results?
  • What did you get?
  • How does what you get differ from what you were expecting?
  • Were your expectations correct in the first place?
  • Can you reproduce the problem (exactly)?

Being able to answer these questions is important not just for your own sake, but in situations where

you may need to ask someone else for help with debugging the problem. Seasoned programmers will

be asking you these exact questions.

20.3 Debugging Tools in R

Watch a video of this section²

R provides a number of tools to help you with debugging your code. The primary tools for debugging

functions in R are

²https://youtu.be/h9rs6-Cwwto

lm(y ~ x) Error in eval (expr, envir, enclos) : object ’y’ not found traceback () 7: eval (expr, envir, enclos) 6: eval (predvars, data, env) 5: model.frame.default(formula = y ~ x, drop.unused.levels = TRUE ) 4: model.frame(formula = y ~ x, drop.unused.levels = TRUE ) 3: eval (expr, envir, enclos) 2: eval (mf, parent.frame ()) 1: lm(y ~ x)

You can see now that the error did not get thrown until the 7th level of the function call stack, in

which case the eval() function tried to evaluate the formula y ∼ x and realized the object y did

not exist.

Looking at the traceback is useful for figuring out roughly where an error occurred but it’s not useful

for more detailed debugging. For that you might turn to the debug() function.

20.5 Using debug()

The debug() function initiates an interactive debugger (also known as the “browser” in R) for a

function. With the debugger, you can step through an R function one expression at a time to pinpoint

exactly where an error occurs.

The debug() function takes a function as its first argument. Here is an example of debugging the

lm() function.

debug (lm) ## Flag the 'lm()' function for interactive debugging lm(y ~ x) debugging in : lm(y ~ x) debug : { ret.x <- x ret.y <- y cl <- match.call () ... if (! qr ) z$qr <- NULL z } Browse[ 2 ]>

Now, every time you call the lm() function it will launch the interactive debugger. To turn this

behavior off you need to call the undebug() function.

The debugger calls the browser at the very top level of the function body. From there you can step

through each expression in the body. There are a few special commands you can call in the browser:

  • n executes the current expression and moves to the next expression
  • c continues execution of the function and does not stop until either an error or the function

exits

  • Q quits the browser

Here’s an example of a browser session with the lm() function.

Browse[ 2 ]> n ## Evalute this expression and move to the next one debug : ret.x <- x Browse[ 2 ]> n debug : ret.y <- y Browse[ 2 ]> n debug : cl <- match.call () Browse[ 2 ]> n debug : mf <- match.call (expand.dots = FALSE ) Browse[ 2 ]> n debug : m <- match ( c ("formula", "data", "subset", "weights", "na.action", "offset"), names (mf), 0L)

While you are in the browser you can execute any other R function that might be available to you

in a regular session. In particular, you can use ls() to see what is in your current environment (the

function environment) and print() to print out the values of R objects in the function environment.

You can turn off interactive debugging with the undebug() function.

undebug (lm) ## Unflag the 'lm()' function for debugging

20.6 Using recover()

The recover() function can be used to modify the error behavior of R when an error occurs.

Normally, when an error occurs in a function, R will print out an error message, exit out of the

function, and return you to your workspace to await further commands.

With recover() you can tell R that when an error occurs, it should halt execution at the exact point

at which the error occurred. That can give you the opportunity to poke around in the environment

in which the error occurred. This can be useful to see if there are any R objects or data that have

been corrupted or mistakenly modified.