Run selected Rmd chunks in a single command

1k views Asked by At

I'm experimenting with Rmd Notebooks, and I'm stuck on something that seems like it should be possible but I cannot figure out a solution at all.

Basically, I would like a functional way to run selected Rmd chunks without compiling with knitr. So I don't think using dependent chunks, caching, etc. will work here.

Here is an example notebook:

Example_Notebook.Rmd

---
title: "Example_Notebook"
output: html_notebook
---

```{r Chunk_1 , include=T}
print(1+2)
Var1 <- 'Variable From Chunk 1'
```

```{r Chunk_2 , include=T}
Var2 <- 'Variable From Chunk 2'
```

```{r Chunk_3 , include=T}
print(Var1)
Var3 <- 'Variable From Chunk 3'
print(Var3)
```

Let's say I wanted to run Chunk 1 & Chunk 3. To do it manually, I could use Ctrl+Shift+Enter while my cursor is in Chunk_1, and then Ctrl+Shift+Enter again while my cursor is in Chunk_3. This would skip Chunk_2 while still getting output for 1 & 3.

I'm looking for a way to do this in a single command/function. This would be similar to the button in RStudio "Run All Chunks Above" except obviously, I would want to skip Chunk_2.

I've tried a lot of ways to write this in a function. The closest I have gotten is with using the rstudioapi package. Here is what my function looks like:

MyNewFunction <- function(){
    rstudioapi::navigateToFile( file = 'Example_Notebook.Rmd' , line = 6  )
    Sys.sleep(.2)
    rstudioapi::executeCommand(commandId = 'executeCurrentChunk')
    Sys.sleep(.2)
    print('First Command Complete')
    
    rstudioapi::navigateToFile( file = 'Example_Notebook.Rmd' , line = 15  )
    Sys.sleep(.2)
    rstudioapi::executeCommand(commandId = 'executeCurrentChunk')
    Sys.sleep(.2)
    print('Second Command Complete')
}

MyNewFunction()

This runs, but when I look at the Example_Notebook.Rmd file, Chunk_1 displays an output, but Chunk_3 does not.
RMD Output

My cursor ends on line 15, so it seems like it runs through navigateToFile, Sleep commands, and print commands, but it waits for the executeCommand until the entire function has has finished.

I've also tried putting the code in the function in its own file and then using source(), as well as wrapping the code in rstudioapi::sendToConsole() but the same thing occurs.

Its almost like I need to execute 2 separate top-level tasks in a single command, but I'm not sure if that's possible or even techinically makes sense.

Looking at the C++ & java code in Rstudio, it seems like the "Run All Chunks Above" command puts all the chunks in to a scope & uses the function "executeScopedChunks". I unfortunately don't understand C++ or java at all so I don't really understand much more than that. It probably isn't helpful, but just in case, I'm looking at that here: https://github.com/rstudio/rstudio/blob/master/src/gwt/src/org/rstudio/studio/client/workbench/views/source/editors/text/TextEditingTarget.java#L5754

Is there any way to solve this? Any help would be very appreciated!

2

There are 2 answers

0
Issa Chi On

First, you can try the "visual" version instead of "source" version, it may make life easier:

enter image description here

Then, you can click the "setting" icon to change chunk 2 or whatever chunk that you do not want to run to "Show nothing (don't run the code)":

enter image description here

And if you want to run all the other chunks without knit, you can just click the 'run' button on the top-right of the toolbar. Click "run all" or other commands you like.

enter image description here

0
xyz On

I do this by sourcing the different chunks with a custom function.

I created the function exec_chunk() that runs in the setup chunk and can later be accessed by declaring the chunk label and the current file.

However, you have to save the file before running the chunk with the exec_chunk() function.

Here is an example if the document you are working on has the name test.Rmd

```{r setup, cache=TRUE}
# Execution function
exec_chunk <- function(chunk_label, file_name) {
  # Read Rmd file
  x <- readLines(paste0("./", file_name))
  message(paste0("Run chunk '", chunk_label, "' from ./", file_name))
  
  # Grep relevant lines
  chunk_start <- (which(grepl(paste0("\\{r ", chunk_label), x)) + 1)
  chunk_signs <- grepl("```", x)
  chunk_end <- (which(chunk_signs)[which(which(chunk_signs) > chunk_start)[1]] - 1)
  chunk_lines <- chunk_start:chunk_end
  
  # Execute
  eval(parse(text=strwrap(paste0(x[chunk_lines]))), envir = .GlobalEnv)
  message(paste0(x[chunk_lines], "\n"))
}
```

```{r chunk_1}
x <- 1
```

```{r chunk_2}
y <- x + 1
```

```{r}
# Execute chunk
exec_chunk("chunk_1", "test.Rmd")
exec_chunk("chunk_2", "test.Rmd")

# Run Code
y + 1
```