Julien
Julien

Reputation: 1695

How to run piped code line by line in R (dplyr)?

Is there any add-in that allows to run piped code line by line in R without altering the code?

For example, I would press keys at each line and it would print the output in the console.

# AS AN EXAMPLE
library(dplyr)
mtcars %>% 
  mutate(cyl2 = 2 * cyl) %>% 
  filter(cyl2 > 15)

I am aware of the ViewPipeSteps add-in but it's not exactly what I am looking for.

Upvotes: 1

Views: 499

Answers (2)

Dan Adams
Dan Adams

Reputation: 5204

I usually just highlight the relevant lines in my script and execute manually (ctrl + enter in Rstudio).

You mentioned going to each line and pressing keys to inspect output up to that point, so what I often do if debugging a long pipe is add .[] (or sometimes head() depending on the object type and what I want to see from it) at the end to just return whatever happened before and then comment out lines I want to remove (which can easily be done with ctrl+shift+c in Rstudio - those are your keypresses). Then I un-comment lines one-by-one as I debug. Finally remove the last line and final %>% once you're satisified.

E.g. I might run these in succession.

library(dplyr)

mtcars %>% 
  slice_head(n = 5) %>% 
  # mutate(cyl2 = 2 * cyl) %>%
  # filter(cyl2 > 15) %>%
  .[]
#>                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#> Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#> Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#> Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#> Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
  
mtcars %>% 
  slice_head(n = 5) %>% 
  mutate(cyl2 = 2 * cyl) %>%
  # filter(cyl2 > 15) %>%
  .[]
#>                    mpg cyl disp  hp drat    wt  qsec vs am gear carb cyl2
#> Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4   12
#> Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4   12
#> Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1    8
#> Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1   12
#> Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2   16

mtcars %>% 
  slice_head(n = 5) %>% 
  mutate(cyl2 = 2 * cyl) %>%
  filter(cyl2 > 15) %>%
  .[]
#>                    mpg cyl disp  hp drat   wt  qsec vs am gear carb cyl2
#> Hornet Sportabout 18.7   8  360 175 3.15 3.44 17.02  0  0    3    2   16

Created on 2022-11-21 with reprex v2.0.2

Upvotes: 1

Allan Cameron
Allan Cameron

Reputation: 173793

A simple way to debug would be to define the following function, which prints out intermediate steps in the pipe while otherwise continuing the calculation:

`%>>%` <- function(a, b) {
  a <- match.call()$a
  b <- match.call()$b
  print(eval(a))
  eval(substitute(a %>% b))
}

For example, if I wanted to debug the following pipe at the second pipe operator:

mtcars <- mtcars[1:5,]

res <- mtcars %>% 
  mutate(cyl2 = 2 * cyl) %>% 
  filter(cyl2 > 15)

I could replace the %>% with %>>% to find out what the state of the calculation was at that step:

res <- mtcars %>% 
   mutate(cyl2 = 2 * cyl) %>>% 
   filter(cyl2 > 15)
#>                    mpg cyl disp  hp drat    wt  qsec vs am gear carb cyl2
#> Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4   12
#> Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4   12
#> Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1    8
#> Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1   12
#> Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2   16

But the correct final calculation is still stored in res

res
#>                    mpg cyl disp  hp drat   wt  qsec vs am gear carb cyl2
#> Hornet Sportabout 18.7   8  360 175 3.15 3.44 17.02  0  0    3    2   16

I'm not sure how useful this would be in practice. Typically if debugging a pipe I would comment out the pipe operator at the end of the line then run the code to see where I'm at, then delete the # and move to the next line. I guess there may be cases where that's inconvenient, but I don't recall seeing any.

Upvotes: 1

Related Questions