Tutorials
r programming

Debug With debugr

In this tutorial, you will learn about debugging in R and Rstudio using the debugr package.

When we talk about debugging in R, there is a slight negative aspect in people who work on python and other programming IDEs. There are some useful functions in R itself like traceback() and browser(), and interactive tools in RStudio but somehow there are few limitations which are not handled by built-in functionalities. In such scenarios, we get stuck with our issues, and that takes much more time to resolve.

Then arrives the debugr package which you can use while writing complex methods and loops which shows you the runtime variable entries and assists in solving the bug in much less time. Although you require preplanning for code entries and the points on an action for debugr. It's worth to put some time in it than resolving the issue the hard way at the time of its execution.

Aspects of debugging in Rstudio

Rstudio provides an interactive platform for debugging that makes detecting bugs in complex functions much easier.

Let's draw a function below and apply these methods.

f <- function(a) g(a) g <- function(b) h(b) h <- function(c) i(c) i <- function(d) j(d) j <- function(e) “a” + e

f(10)

Here you can browse to different functions to check the code in an iterative way. The function you browse will show its code.

You can use traceback to see the flow of function calls made by individual ones.

Debugging on error

While executing code in Rstudio, if an error comes then Rstudio provides two methods in its interactive console to resolve it. One is traceback that shows you the flow of the function calls, and the other is Rerun with debug. If you choose rerun with debug, Rstudio will take you to the interactive debugger session which also pauses the execution where the error occurred.

When you are in the editor you can use it either with the or with the keyboard:

  • , n: This button will take you to the next step.

  • , or s: works like next, but instead of next step it steps into next function.

  • , or f: finishes execution of the current loop or function.

  • , c: leaves interactive debugging.

  • , Q: stops debugging, terminates the function, and returns to the global workspace.

Setting Breakpoints in arbitrary code

Rstudio enters in the interactive console on an error, but you can enter at an arbitrary code location by using either a Rstudio breakpoint or browser().

The breakpoint can be added through several methods:

  1. You can click on the left of the line of the code.
  2. You can press Shift+F9 on the line of the code.
  3. You can add browser() where the execution needs to be stopped.

RStudio currently does not support conditional breakpoints that put a breakpoint by passing criteria, which is somewhat handled in the debugr package discussed in this tutorial. *

For details on these debugging methods visit here.

Now let's talk about the package debugr.

Debugr supports a simpler aspect of debugging which is easy to understand if you are involved in less debugging work. Debugr has a few simple functions, they are:

  • debugr_isActive:- Switching debug mode on and off.
  • debugr_switchOff:- Switching debug mode on and off.
  • debugr_switchOn:- Switching debug mode on and off.
  • dwatch:- Printing debug outputs during runtime.

Out of all these functions, dwatch plays the most crucial role. It prints a debug output to a console or a file in a more complicated case. The output can be static text, one or many values of the variables.

For any debugging function, you need switch on the debugging functionality of debugr which is easily done by debug_switchOn(). You can put your dwatch() function anywhere you want to debug the code especially in production level code and debug it whenever a situation came by switching it on and later switch it off by using debugr_switchOff() function.

Let's look at the structure of the dwatch function in a sample code.

library(debugr)

debugr_switchOn()

myfunction <- function(x) {

  z <- 1

  for(i in 1:x) {
    dwatch(crit = "z > 40000", objs = c("z", "i"))
    z <- z * i
  }
  # avoiding to print the z
  invisible(z)
}

myfunction(10)
##
## ----------------------------- DEBUGR MESSAGE ------------------------------
##
## ** z:
## [1] 40320
##
##
## ** i:
## [1] 9
##
## ---------------------------------------------------------------------------
##
## ----------------------------- DEBUGR MESSAGE ------------------------------
##
## ** z:
## [1] 362880
##
##
## ** i:
## [1] 10
##
## ---------------------------------------------------------------------------
debugr_switchOff()

Here the code is going through iterative multiplication, or you can apply any case used in your functions, the dwatch function applied to the variable z with the criteria z > 4000. So as a result messages are printed when the criteria is fulfilled and the desired results got printed that is values of z and i variables.

You can use some sophisticated arguments that manipulate the format of the output.

debugr_switchOn()

myfunction <- function(x) {

  z <- 1

  for(i in 1:x) {
    dwatch(crit = "z > 40000", expr=c("format(z, big.mark = \",\")", "format(i, big.mark = \",\")"))
    z <- z * i
  }
  # avoiding to print the z
  invisible(z)
}

myfunction(10)
##
## ----------------------------- DEBUGR MESSAGE ------------------------------
##
## ** Expression: format(z, big.mark = ",")
## [1] "40,320"
##
## ** Expression: format(i, big.mark = ",")
## [1] "9"
## ---------------------------------------------------------------------------
##
## ----------------------------- DEBUGR MESSAGE ------------------------------
##
## ** Expression: format(z, big.mark = ",")
## [1] "362,880"
##
## ** Expression: format(i, big.mark = ",")
## [1] "10"
## ---------------------------------------------------------------------------
debugr_switchOff()

There are few more arguments that you can incorporate:

  • show.all: By setting this argument TRUE, you can see all the objects for the criteria.
  • msg: It is used to add a static text message.
  • show.frame: By setting this argument as FALSE, you can remove upper and lower border.
  • halt: By setting this argument as TRUE, you can stop the transaction as soon as the criteria is fulfilled.

If you would like to learn more about debugging in R, take DataCamp's Working with the RStudio IDE (Part 1) course.

Want to leave a comment?