R Debug: List of Important R Debug Functions

1. R Debug Functions – Objective

In this R tutorial on R debug, we are going to discuss the very interesting topic i.e. R Debugging. Here we will discuss What is Debugging, What is the fundamental principle of Debugging in R programming. We will also cover the different functions for Debugging in R with the help of examples in this R programming tutorial.

So, let’s start R Debug tutorial.

R Debug: List of Important R Debug Functions

R Debug: List of Important R Debug Functions

2. What is R Debug?

A grammatically correct program may give us incorrect results due to logical errors. In case, if such errors (i.e. bugs) occur, we need to find out why and where they occur so that you can fix them. The procedure to identify and fix bugs is called “debugging”.
There are number of R debug Functions, such as:

  • traceback()
  • debug()
  • browser()
  • trace()
  • recover()

We will discuss the above-mentioned functions one-by-one in the later section of this blog.

3. Fundamental Principles of R Debugging

Programmers often find that they spend more time debugging a program than actually writing it. Good debugging skills are invaluable.

i. The essence of debugging

The principle of confirmation
Fixing a bugging program is a process of confirming, one by one, that the many things you believe to be true about code actually are true. When we find one of our assumptions is not true, we have found a clue to the location of a bug.
For Example:
x <- y^2 + 3*g(z, 2)
w <- 28
if (w+q > 0) u <- 1 else v <- -10

ii. Start Small

At least at the beginning of the r debug process, stick to small simple test cases. Working with large data objects may make it harder to think about the problem. Of course, we should eventually test our code in large, complicated cases, but start small.

iii. Debug in a Modular

Top-Down Manner
Most good software developers agree that code should be written in a modular manner. Our first-level code should not be long with much of it consisting of functions calls. And those functions should not be too lengthy and should call another function if necessary. This makes code easier at the writing stage and also easier for others to understand when it comes time for the code to be extended.
We should debug in a top-down manner, too. Suppose we have a set the debug status of our function
f() and f() contains this line.
For Example:
Y <- g(x,8)
Do not call debug (g) yet. Execute that line and see g() returns the value we expect. If it does then we have to just avoid the time-consuming process of single-stepping Through g(). If g() returns the wrong value, then now is the time to call debug(g).

iv. Antibugging

If we have a section of a code in which a variable x should be positive. We can insert this line:
Stopifnot(x>0)
If there is a bug earlier in the code that renders x equals to, say -3, the call to stopifnot() will bring things right there, with an error message like this:
Error: x > 0 is not TRUE

R Quiz

4. R Debug Functions

Now we will discuss the above-mentioned functions for debugging in R.

i. traceback()

If our code has already crashed and we want to know where the offending line is, try traceback(). This will (sometimes) show where abouts in the code the problem occurred.
When an R function fails, an error is printed to the screen. Immediately after the error, you can call traceback() to see in which function the error occurred. The traceback() function prints the list of functions that were called before the error occurred. The functions are printed in reverse order.
For Example:

f<-function(x) {
r<-x-g(x)
r
}
g<-function(y) {
r<-y*h(y)
r
}
h<-function(z) {
r<-log(z)
if(r<10)
r^2
else
r^3
}
> f(-1)
Error in if (r < 10) r^2 else r^3: missing value where TRUE/FALSE needed
In addition: Warning message:
In log(z) : NaNs produced
> traceback()
3: h(y)
2: g(x)
1: f (-1)

ii. debug()

The function debug() in R allows one to step through the execution of a function, line by line. At any point, we can print out values of variables or produce a graph of the results within the function. While debugging, we can simply type “c” to continue to the end of the current section of code. traceback() does not tell us where in the function the error occurred. In order to know which line causes the error, we may want to step through the function using debug().
For Example:
Compute the sum of squared error SS = ∑ni=1(xi−μ)

## compute sum of squares
SS<-function(mu,x) {
d<-x-mu
d2<-d^2
ss<-sum(d2)
ss
}
# set seed to get reproducible results
> set.seed(100)
> x<-rnorm(100)
> SS(1,x)
[1] 202.5615
## now start debugging
> debug(SS)
> SS(1,x)
debugging in: SS(1, x)
debug: {
d <- x - mu
d2 <- d^2
ss <- sum(d2)
ss
}
attr(,"srcfile")
C:\Users\jihk\doc\courses\StatisticalComputing\lecture5\debugex2.R
Browse[1]>

After you see the “Browse[1]>” prompt, you can do different things:

  • Typing n executes the current line and prints the next one;
  • By typing Q, we can quit the debugging;
  • Typing where tells where you are in the function call stack;
  • By typing ls(), we can list all objects in the local environment;

Typing an object name or print(<object name>) tells us current value of the object. If your object has name n, c or Q, we have to use print() to see their values.

iii. browser()

The R debug function ‘browser()’ stops the execution of a function until the user allows it to continue. This is useful if we don’t want to step through all the code, line-by-line, but we want it to stop at a certain point so we can check out what is going on. Inserting a call to the browser() in a function will pause the execution of a function at the point where the browser() is called. Similar to using debug() except we can control where execution gets paused.
For Example:

h<-function(z) {
browser() ## a break point inserted here
r<-log(z)
if(r<10)
r^2
else
r^3
}
> f(-1)
Called from: h(y)
Browse[1]> ls()
[1] "z"
Browse[1]> z
[1] -1
Browse[1]> n
debug: r <- log(z)
Browse[1]> n
debug: if (r < 10) r^2 else r^3
Browse[1]> ls()
[1] "r" "z"
<strong>Warning message:</strong>
In log(z) : NaNs produced
Browse[1]> r
[1] NaN
Browse[1]> c
Error in if (r < 10) r^2 else r^3 : missing value where TRUE/FALSE needed
> 

iv. trace()

Calling trace() on a function allows the user to insert bits of code into a function. The syntax for R debug function trace() is a bit strange for first time users. It might be better off using debug().
For Example:

> as.list(body(h))
[[1]]
‘{‘
[[2]]
r <- log(z)
[[3]]
if (r < 10) r^2 else r^3
attr(,"srcfile")
C:\Users\jihk\doc\courses\StatisticalComputing\lecture5\debugex1.R
> trace("h",quote(if(is.nan(r)) {browser()}), at=3, print=FALSE)
> f(1)
[1] 1
> f(-1)
Called from: eval(expr, envir, enclos)
Browse[1]> ls()
[1] "r" "z"
<strong>Warning message:</strong>
In log(z) : NaNs produced
Browse[1]> r
[1] NaN
Browse[1]> z
[1] -1
Browse[1]> c
...
>
> trace("h",quote(if(z<0) {z<-1}), at=2, print=FALSE)
[1] "h"
> f(-1)
[1] -1

v. recover()

When we are debugging a function, recover() allows us to check variables in upper level functions.
For Example:

> trace("h",quote(if(is.nan(r)) {recover()}), at=3, print=FALSE)
[1] "h"
> f(-1)
Enter a frame number, or 0 to exit
1: f(-1)
2: g(x)
3: h(y)
Selection: 1
Called from: eval(expr, envir, enclos)
Browse[1]> ls()
[1] "x"
Warning message:
In log(z) : NaNs produced
Browse[1]> x
[1] -1
Browse[1]> c
Enter a frame number, or 0 to exit
1: f(-1)
2: g(x)
3: h(y)
Selection: 2
Called from: eval(expr, envir, enclos)
Browse[1]> ls()
[1] "y"
Browse[1]> y
[1] -1
Browse[1]> c
Enter a frame number, or
Enter 0 to exit
1: f(-1)
2: g(x)
3: h(y)
Selection: 3
Called from: eval(expr, envir, enclos)
Browse[1]> ls()
[1] "r" "z"
Browse[1]> r
[1] NaN
Browse[1]> z
[1] -1
Browse[1]> c
Enter a frame number, or
Enter 0 to exit
1: f(-1)
2: g(x)
3: h(y)
Selection: 0
Error in if (r < 10) r^2 else r^3: missing value where TRUE/FALSE needed

  • We can use recover() as an error handler, set using options() (e.g.options(error=recover)).
  • When a function throws an error, execution is halted at the point of failure. We can browse the function calls and examine the environment to find the source of the problem.

So, this was all on R debug. Hope you like our explanation on R debug functions.

5. Conclusion – R Debug

Hence, in this tutorial on R debug Functions, we have discussed Debugging in R along with their functions in detail with the examples. Hope you like this blog. If you have any query related to Debugging in R, so, feel free to share with us. Hope we will help you out.
See Also-

Reference for R

Leave a Reply

Your email address will not be published. Required fields are marked *