I have a Rmarkdown document where the garbage collector is used to save memory during renderization. The function gc() is called at the end of some code chunks for convenience, but I would like to hide its output, while showing other code in the same chunk (e.g. a plot). If this output is impossible to hide without using eval=FALSE or include=FALSE (eg. with gc() in a separate chunk), then I would like to understand why, and if this might happen for other functions as well.
Example code to reproduce the problem is given below:
---
title: "Example"
output:
html_document
---
```{r, message=FALSE, warning=FALSE, echo=FALSE}
library("tidyverse")
```
```{r, message=FALSE, warning=FALSE, echo=FALSE}
df <- mtcars %>% dplyr::group_by(cyl) %>% dplyr::summarise(meanMPG = mean(mpg))
df %>% ggplot() + geom_point(aes(x=cyl, y=meanMPG))
rm(df); gc(verbose = FALSE, full = FALSE)
```
EDIT: as you can note, the problem persist even when the options verbose=FALSE and full=FALSE are used in gc().
Related
I have a piece of RMarkdown code that runs fine in one block.
```{r}
library(tidyverse)
data("PlantGrowth")
set.seed(1234)
PlantGrowth %>% sample_n_by(group, size = 1)
levels(PlantGrowth$group)
```
However, if I try to break it into pieces of code, which I need to do in order to add explanations, I get the following error in the RMarkdown console.
```{r eval=TRUE}
library(tidyverse)
data("PlantGrowth")
set.seed(1234)
```
Comment the code here
```{r eval=TRUE}
PlantGrowth %>% sample_n_by(group, size = 1)
levels(PlantGrowth$group)
```
Say more stuff...
Error in PlantGrowth %>% sample_n_by(group, size = 1) : could not find function "%>%" Calls: <Anonymous> ...withVisible -> eval_with_user_handlers -> eval -> eval Execution Halted.
Is there a way to make markdown carry over the libraries and variables loaded in previous code blocks up to the end of the document?
Make sure you insatlled tidyverse and rstatix in your env.
```{r eval=TRUE}
library(tidyverse)
library(rstatix)
data("PlantGrowth")
set.seed(1234)
```
Comment the code here
```{r eval=TRUE}
PlantGrowth %>% sample_n_by(group, size = 1)
levels(PlantGrowth$group)
```
I have a list of 300 plots and want one PowerPoint slide to show one plot (300 slides). What's the best way to achieve this?
A toy example using the built-in iris dataset to create a list of plots:
purrr::map(names(iris[,-5]), function(col_name){
plot = iris %>%
ggplot(aes(x = !!as.name(col_name))) +
geom_histogram()
return(plot)
})
I hope to create PowerPoint slides with one plot on each slide.
I will be using the iris data set, which is a built-in data set often used to populate example code.
With the following code in a Rmd file:
---
title: "Test_PowerPoint"
author: "KoenV"
date: '2022-06-30'
output: powerpoint_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
```{r include=FALSE, warning=FALSE, message=FALSE}
library(tidyverse)
library(purrr)
```
```{r, iris, fig.cap="A scatterplot.", echo=FALSE, warning=FALSE, message=FALSE}
## your code
purrr::map(names(iris[,-5]), function(col_name){
plot = iris %>%
ggplot(aes(x = !!as.name(col_name))) +
geom_histogram()
return(plot)
})
```
And after hitting the "knit" button, you will see a PowerPoint presentation appearing, with the following lay-out:
Please let me know, whether this is what you wanted.
I am creating a series of plots from within a loop in an RMarkdown document, then knitting this to a PDF. I can do this without any problem, but I would like the caption to reflect the change between each plot. A MWE is shown below:
---
title: "Caption loop"
output: pdf_document
---
```{r, echo=FALSE}
library(tidyverse)
p <-
map(names(mtcars), ~ggplot(mtcars) +
geom_point(aes_string(x = 'mpg', y = .))) %>%
set_names(names(mtcars))
```
```{r loops, fig.cap=paste(for(i in seq_along(p)) print(names(p)[[i]])), echo=FALSE}
for(i in seq_along(p)) p[[i]] %>% print
```
I have made a first attempt at capturing the plots and storing in a variable p, and trying to use that to generate the captions, but this isn't working. I haven't found too much about this on SO, despite this surely being something many people would need to do. I did find this question, but it looks so complicated that I was wondering if there is a clear and simple solution that I am missing.
I wondered if it has something to do with eval.after, as with this question, but that does not involve plots generated within a loop.
many thanks for your help!
It seems that knitr is smart enough to do the task automatically. By adding names(mtcars) to the figure caption, knitr iterates through these in turn to produce the correct caption. The only problem now is how to stop all of the list indexes from printing in the document...
---
title: "Caption loop"
output: pdf_document
---
```{r loops, fig.cap=paste("Graph of mpg vs.", names(mtcars)), message=FALSE, echo=FALSE, warning=FALSE}
library(tidyverse)
map(
names(mtcars),
~ ggplot(mtcars) +
geom_point(aes_string(x = 'mpg', y = .))
)
```
In case this might be useful to somebody. Here is an adaptation of Jonny's solution for captions without printing list indices. This can be achieved by using purrr::walk instead of purrr::map. Also included is a latex fig label and text that references each plot.
---
title: "Loop figures with captions"
output:
pdf_document
---
```{r loops, fig.cap=paste(sprintf("\\label{%s}", names(mtcars)), "Graph of mpg vs.", names(mtcars)),results='asis', message=FALSE, echo=FALSE, warning=FALSE}
library(tidyverse)
library(stringi)
walk(names(mtcars),
~{
p <- ggplot(mtcars) +
geom_point(aes_string(x = 'mpg', y = .))
#print plot
cat('\n\n')
print(p)
#print text with refernce to plot
cat('\n\n')
cat(sprintf("Figure \\ref{%s} is a Graph of mpg vs. %s. %s \n\n", ., .,
stri_rand_lipsum(1)))
cat("\\clearpage")
})
```
I have to repeat certain outputs in many rmarkdown reports and want to write a function to use for this.
Calling a function outputs plots ok when I knit the rmd file but not kable data frames.
For example
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r mtcars}
make_outputs <- function(){
knitr::kable(head(mtcars))
plot(mtcars$mpg, mtcars$cyl)
hist(mtcars$cyl)
}
make_outputs()
```
Displays the plots but not the kable table.
You can do this by using print to print the kable output, setting the results="asis" of the code chunk and then using kable_styling from package kableExtra.
This works for me:
```{r mtcars, results='asis'}
library(kableExtra)
library(knitr)
make_outputs <- function(){
print(kable_styling(kable(head(mtcars))))
plot(mtcars$mpg, mtcars$cyl)
hist(mtcars$cyl)
}
make_outputs()
```
Using a return statement with all objects in a list can help here, You can try recordPlot or plot from base R to solve your problem, By putting each of these plots in list, I managed to get the plots along with your table. Changed your code a bit in return statement to plot each of the plots along with tables like this.
Option1:
Using list in return with all the objects binded together without using lapply in function call
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r mtcars}
make_outputs <- function(){
return(list(hist(mtcars$cyl),
knitr::kable(head(mtcars)),
plot(mtcars$mpg, mtcars$cyl)))
}
make_outputs()
```
Another version (In case you don't want the code to print hist output to your html then you can use below function to suppress it.
make_outputs <- function(){
h1 <- plot(hist(mtcars$cyl, plot=FALSE))
h2 <- knitr::kable(head(mtcars))
h3 <- plot(mtcars$mpg, mtcars$cyl)
return(list(h1, h2, h3))
}
Option2:
Another (better version by using invisible function on lapply to suppress NULL printing, then using results='asis' option in the markdown settings as below gives a clean output than earlier.
---
title: "Markdown example"
output: html_document
---
knitr::opts_chunk$set(echo = FALSE)
knitr::opts_knit$set(root.dir= normalizePath('..'))
knitr::opts_chunk$set(error = FALSE)
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r mtcars, results='asis'}
make_outputs <- function(){
return(list(plot(hist(mtcars$cyl, plot =FALSE)),
knitr::kable(head(mtcars)),
plot(mtcars$mpg, mtcars$cyl)))
}
invisible(lapply(make_outputs(), print))
```
This has given me a histogram, a scatter plot and a table in the knitted html document. Hope this helps, Not sure though if you wanted this way. Please let me know in case you wanted in any other way.
The problem seems to be related to knitr::kable incorrectly detecting the environment for the printing when it is embedded inside a function. This interferes with its ability to correctly figure out how to format. We can hack around this by placing the object to print in the top level environment before we print it.
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
print_kable = function(x) {
print(kable_print_output <<- x)
cat('\n')
}
```
# Markdown example
```{r mtcars, results='asis'}
make_outputs <- function() {
print_kable(knitr::kable(head(mtcars)))
plot(mtcars$mpg, mtcars$cyl)
print_kable(knitr::kable(tail(mtcars)))
}
make_outputs()
```
I got something similar working by
moving the knitr::kable(head(mtcars)) inside a return() at the end of the function.
including results = 'asis'
e.g.
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r results = 'asis'}
make_outputs <- function(){
print(plot(mtcars$mpg, mtcars$cyl))
print(hist(mtcars$cyl))
return(knitr::kable(head(mtcars)))
}
make_outputs()
```
If you use ggplot for plots, you will need to wrap your plot inside print()
Reproducible example below. I lose formatting on the table whenever I include a ggvis figure.
---
title: "test"
output: html_document
---
```{r setup, include=FALSE}
library(dplyr)
library(ggvis)
library(knitr)
```
The following table looks fine...
```{r echo=FALSE, results='asis'}
cars %>% kable(format = 'markdown')
```
As long as I don't include this plot below
```{r, echo=FALSE}
pressure %>%
ggvis(x = ~temperature, y = ~pressure) %>%
layer_bars()
```
This is probably related to a bug that has been fixed in the development version of ggvis. If you install the latest with devtools::install_github('rstudio/ggvis'), it should work.