Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge consecutive console outputs into one block

Tags:

r

rstudio

knitr

When knitting R-Markdown in RStudio, I would like to all console outputs in one chunk to be placed together in one code block. How can this be done?

As a workaround, I write two code blocks of the same code and set eval=FALSE on the first block and echo=FALSE on the second.

```{r Vector Demo 2, eval=FALSE}
# examine the class and structure of vectors
class(nums)
class(char)
str(nums)
str(char)
```
```{r Vector Demo 2b, echo=FALSE}
# examine the class and structure of vectors
class(nums)
class(char)
str(nums)
str(char)
```

This however produces the following output:

# examine the class and structure of vectors
class(nums)
class(char)
str(nums)
str(char)
## [1] "numeric"
## [1] "character"
##  num [1:5] 1 2 3 4 5
##  chr [1:3] "A" "B" "C"

What I would like is to have the output of the second chunk (i.e. Vector Demo 2b) to be placed together in one code block just like the first chunk (i.e. Vector Demo 2).
This is a sample output of how I would prefer to have my result:

# examine the class and structure of vectors
class(nums)
class(char)
str(nums)
str(char)
## [1] "numeric"
## [1] "character"
##  num [1:5] 1 2 3 4 5
##  chr [1:3] "A" "B" "C"

Note to bounty hunters:
Better still, I would be grateful for a way to have one code chunk first print the input code, and then print the output code. That way I could avoid duplication and possible inconsistencies that could come with it.

like image 920
Alex Essilfie Avatar asked Mar 05 '14 04:03

Alex Essilfie


3 Answers

Here is a solution to your problem. There are two things to do:

## Test


```{r echo = F, cache = F}
knitr::knit_hooks$set(document = function(x){
  gsub("```\n*```r*\n*", "", x)
})
```

```{r VectoDemo, results = 'hold'}
nums = 1:5
char = LETTERS[1:5]
# examine the class and structure of vectors
class(nums)
class(char)
str(nums)
str(char)
```

I have done two things here

  1. Set results = 'hold' to "hold" printing of output after source is printed.
  2. Added a document hook to collapse successive code chunks with no text in-between.
like image 85
Ramnath Avatar answered Nov 12 '22 22:11

Ramnath


With knitr >= 1.5.23

You can get quite a bit of variety from the built-in knitr options.

For instance... get the same results as Ramnath's hook using collapse=TRUE, results="hold" (no global document hook needed).

If you really want distinct source/output parts as shown in the question then you are already on the right path. Just make use of chunk reuse to get the output combo without having to repeat yourself...

```{r}
nums <- 1:5
char <- LETTERS[1:3]
```

```{r "Vector Demo", eval=FALSE}
# examine the class and structure of vectors
class(nums)
class(char)
str(nums)
str(char)
```

```{r "Vector Demo", echo=FALSE}
```

The last chunk is your basic chunk reuse pattern.

You can see a variety of the basic combinations here.

Since you aren't making a knitr tutorial ignore the source and use the rendered examples.

like image 32
Thell Avatar answered Nov 12 '22 23:11

Thell


@Ramnath's solution appears a bit simpler than this one. His is likely better in many (most?) circumstances, but this alternate solution might be good in others:

Test.

```{r echo=F,cache=F}
knitr::knit_hooks$set(document=function(x) {
    paste(rapply(strsplit(x, '\n'), function(y) Filter(function(z) !grepl('# HIDEME',z),y)), collapse='\n')
})
```

```{r Vector Demo 1, results='hold', tidy=FALSE}
nums = 1:5
chars = LETTERS[1:5]
# examine the class and structure of vectors
{ # HIDEME
print(class(nums))
print(class(chars))
str(nums)
str(chars)
} # HIDEME
```

Notes:

  1. Use of the brackets ({ and }) around the code keeps the output together. However, commands that return things and don't print things will be silent (unless last), ergo my print addition to those lines. This may or may not be a factor depending on your actual commands.

  2. In my install, for some reason, tidy defaults to TRUE which was shifting my first # HIDEME comment to before the left bracket (and I have since edited to code to reflect the definition of nums and chars). Odd, but likely a side-effect of source tidying. This is why I force tidy=FALSE. Since this might affect how you present your code, using it as a per-block option at least limits the pretty-printing problem.

  3. The # HIDEME is really just "comment-character plus some obscure string" for easy greping.

  4. The knit_hook I added is not "simple," but I find it less likely to have side-effects on other chunks within a document. This could likely be done with more specificity (I know @Ramnath has worked on other knitr problems with Yihui, so there could be more "correct" ways to do this with more specificity.) (I tried and failed to do this as an "output" hook instead of "document" hook. Homework.)

like image 42
r2evans Avatar answered Nov 12 '22 22:11

r2evans