How to display hundreds of plots neatly in Rmarkdown? - r

I have a loop code that generate 100 different plots from a subset of a data. The simplified version of the code is as follow:-
for (i in 1:100) {
df <- alldata[alldata$id==i,]
plot(df)
}
The problem is I need to use R markdown to display the results. However, in the above code, the 100 plots will be display one after another in long pages, which will be very untidy.
I would like to display one plot at a time, but allow the viewer to click on the 'next page' to see the next plot. Is it possible to do so in R markdown?
Thanks and sorry if my question is too easy, as I am completely new to this (first time coding).

You can try my approach. I used html_document and tabsets ... works fine for my needs.
---
title: "Plot in loops"
output: html_document
---
# Title {.tabset .tabset-fade}
```{r, results='asis'}
for (i in 1:100) {
df <- data.frame(
x = 1:100,
y = runif(100)
)
cat( paste('## title no.', i, '\n' ) )
plot(df)
cat('\n \n')
}
```

Related

Print a plot I have saved in the environment anywhere in Rmarkdown

I create an Rmarkdown document where I would like to create a plot at the start of the document, and then print it at the end of the document.
I thought the best way to achieve this would be to save the plot in the environment and then recall it later, I save this as follows:
plot(1:5, 1:5) ; plot1 <- recordPlot() # I create a plot and save it as plot1
This plot is saved under "Data" in the environment.
If I enter plot1 into the console, my plot is reproduced, but when I try to display it directly in Rmarkdown as follows I get the following error:
plot(plot1)
Error in xy.coords(x, y, xlabel, ylabel, log) :
'x' is a list, but does not have components 'x' and 'y'
How I can take the plot that I saved into Data and print it anywhere I would like in my Rmarkdown document?
p.s. I know it's tempting to say to repeat the plot again later in the document, but the parameters that build the plot are subsequently altered for another part of my analysis.
Re-producible example:
x = 1
plot_later <- function() {
plot(x)
}
plot_later()
x = -10
plot_later()
X starts at 1 then changes to -10 on the Y axis, I want it to stay at the initial value of 1.
Solution based on https://bookdown.org/yihui/rmarkdown-cookbook/reuse-chunks.html :
---
title: plot now, render later
output: html_document
---
We put some plot expression here to evaluate it later:
```{r, deja-vu, eval=FALSE}
x = 1
plot(x)
```
Here we change `x` - but only within the corresponding chunk's scope:
```{r}
x = 10
```
... moving on
Here, we evaluate and plot the expression defined earlier; x is taken from that chunk's scope, so it still evaluates to `1`:
```{r, deja-vu, eval=TRUE}
```
One option could be saving the plot as grob object using as.grob function from ggplotify and then print it elsewhere.
---
title: "Saving A Plot"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
```{r}
library(ggplotify)
library(grid)
show_captured_plot <- function(grb) {
grid::grid.newpage()
grid::grid.draw(grb)
}
```
```{r}
x <- 1
p <- as.grob(~plot(x))
```
Now we can plot the figure here.
```{r}
x <- 10
show_captured_plot(p)
```
here, check out this link: https://bookdown.org/yihui/rmarkdown-cookbook/fig-chunk.html
It has a lot of instructions on how to get started with rmarkdown.
Specifically answering your question:
We generate a plot in this code chunk but do not show it:
```{r cars-plot, dev='png', fig.show='hide'}
plot(cars)
```
After another paragraph, we introduce the plot:
![A nice plot.](`r knitr::fig_chunk('cars-plot', 'png')`)
Basically you have to save your graph as a variable and then call on it using the knitr::fig_chunk() function.

R markdown: Use for loop to generate text and display figure/table

I think the R markdown can generate sections of text using for loop, see this post. However, I wonder if there is any possibility to generate figures and tables as well.
So I made a simple example. Assume in R markdown, I want to have the markdown language and display the table and plot below.
This will return a table and a plot.
df<- data.frame(
name = LETTERS[1:12],
data = runif(n = 12))
new_df<-some_function(df,1)
formattable(new_df)
plot(new_df$data)
where some_function is a simple function that does the following
some_function<-function(df,loc){
df$data<-df$data+loc
return(df)
}
So I hope to get this repeated 5 times, which means generating the below selection 5 times.
This will return a table and a plot.
(figure: pretend there displayed a figure)
(table: pretend there displayed a table)
How should I write the code using some template to display the tables and figures? The code for generating a list of new_df is below.
df_list=list()
for (i in 1:5){
new_df<-some_function(df,i)
df_list[[i]]<-new_df
}
The goal is to display the tables formattable(df_list[[i]]) and figures plot(df_list[[i]]$data) under the 5 separate sections. (Assume each section will have more meaningful text content than the example I made) Something like this screktch below.
template <- "## This will return a table and a figure.
Table is: formattable(df_list[[i]])
Figure is: plot(df_list[[i]]$data)
"
for (i in 1:5) {
current <- df_list[[i]]
cat(sprintf(template, current,current$data))
}
Is that possible to accomplish this? Any thoughts or ideas are very welcome.
You can use result = 'asis' inside the r chunk and use cat() to create the sections.
---
title: "R Notebook"
output:
html_document
---
## Example
```{r, results='asis'}
require(ggplot2)
for(i in 1:5){
cat("### Section ", i, "\n")
df <- mtcars[sample(5),]
tb <- knitr::kable(df, caption = paste0("Table",i))
g1 <- ggplot2::ggplot(df, aes(x = mpg, y = disp, fill = gear)) +
ggplot2::geom_point() +
ggplot2::labs(title = paste0("Figure ", i))
cat("\n")
print(g1)
print(tb)
cat("\n")
}
```

Dynamic plots and tables inside Rmarkdown

I am new to Rmarkdown and shiny and forgive me for some naive questions. I have build a code in two parts first where I do all the processing and second where I call the Rmarkdown to knit it.
The first code example.R is as follows and works fine independently (with only glitch of plots being trimmed from sides):
# Create a label for the knitr code chunk name
## #knitr ExternalCodeChunk020
library(Seurat)
library(tidyverse)
library(sleepwalk)
library(gridExtra)
library(plotly)
library(DT)
# Set up some sample data
data(mtcars)
# Display the xvars
# Note that I don't really want to display the xvars, but this line is included
# to demonstrate that text output won't show up in the RMarkdown in this example.
a <- ggplotly(ggplot(mtcars, aes(cyl,mpg)) + geom_boxplot())
b <- ggplotly(ggplot(mtcars, aes(wt,mpg)) + geom_point())
subplot(a, b, nrows=1)
DT::datatable(mtcars, class = "cell-border stripe", rownames = FALSE, filter ="top",
editable =TRUE, extension = "Buttons", options = list(dom="Bfrtip",
buttons =c("copy", "csv", "excel", "pdf","print")))
ggplotly(ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=5))
# Display the date and time
# Similar to xvars above, this line is intended to demonstrate that text output
# won't be displayed in this RMarkdown example.
Sys.Date()
The second part of the code (mrkdwn.Rmd) is where I try to knit and generate Rmarkdown report:
---
title: "Code Chunks"
author: "Author"
date: "November 13, 2020"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
knitr::read_chunk("example.R")
```
This first code chunk prints the externally located code,
but it does not execute the code. The next code chunk
executes the externally located code, but it does not print code
itself. Text output is suppressed, and figures are plotted,
but only after all of the code is executed.
```{r DisplayCodeChunk, eval = FALSE, echo = FALSE}
<<ExternalCodeChunk020>>
```
```{r RunCodeChunk, echo = FALSE, eval = TRUE, results = 'hide'}
<<ExternalCodeChunk020>>
```
the output doesn't contain plots. I am not sure what is going wrong, could anyone of you help me in fixing this.
I know that an easy fix is to put both parts of the code together inside the Rmarkdown like this:
---
title: "test3"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r}
library(Seurat)
library(tidyverse)
library(sleepwalk)
library(gridExtra)
library(plotly)
library(DT)
# Set up some sample data
data(mtcars)
# Display the xvars
# Note that I don't really want to display the xvars, but this line is included
# to demonstrate that text output won't show up in the RMarkdown in this example.
a <- ggplotly(ggplot(mtcars, aes(cyl,mpg)) + geom_boxplot())
b <- ggplotly(ggplot(mtcars, aes(wt,mpg)) + geom_point())
subplot(a, b, nrows=1)
DT::datatable(mtcars, class = "cell-border stripe", rownames = FALSE, filter ="top",
editable =TRUE, extension = "Buttons", options = list(dom="Bfrtip",
buttons =c("copy", "csv", "excel", "pdf","print")))
ggplotly(ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=5))
# Display the date and time
# Similar to xvars above, this line is intended to demonstrate that text output
# won't be displayed in this RMarkdown example.
Sys.Date()
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Since I need to process large datasets and generate graphs/plots and table I would prefer to keep them separately, so that my Rmarkdown doesn't crash. May be this is wrong and there could be a better approach, please suggest.
Many thanks for your time and help.

RMarkdown: Multiple ggplots in same chunk using loop

I am trying to generate multiple plots (in ggplot2) using a for loop within a single chunk in an RMarkdown document.
When I hardcode the code to generate the two plots, the plots are rendered as expected. See section in my code titled "Hardcoded Method".
But, when I load the parameters for the two plots in a list and loop through the list, the plots are not showing up. I don't see any errors either. Please see section of my code titled "Loop Method".
Can anyone please tell me what is going on and how I can fix it? Thanks.
Karthik.
Here is my code:
---
title: "Test for multiple plots"
author: "KC"
date: "4/3/2020"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Hardcoded Method
Sample Plot - One plot at a time
```{r Multiple Plots separately listed, echo=TRUE, fig.keep="all"}
library(ggplot2)
library(datasets)
combo = c("temperature", "pressure")
ggplot(pressure,
mapping=aes(x=base::get(combo[1]), y=base::get(combo[2]))) +
geom_point() +
labs(x=combo[1],
y=combo[2],
title=paste("Hardcoded Method:", paste(combo, collapse=" vs ")))
combo = c("pressure", "temperature")
ggplot(pressure,
mapping=aes(x=base::get(combo[1]), y=base::get(combo[2]))) +
geom_point() +
labs(x=combo[1],
y=combo[2],
title=paste("Hardcoded Method:", paste(combo, collapse=" vs ")))
```
# Loop Method
Now, I use a loop method to generate the same plots.
```{r Multiple Plots in a loop, echo=TRUE, fig.keep="all"}
library(ggplot2)
library(datasets)
combos = list(c("temperature", "pressure"), c("pressure", "temperature"))
for (combo in combos) {
# combo = combos[[1]]
print(paste("Plotting", paste(combo, collapse=" vs ")))
ggplot(pressure,
mapping=aes(x=base::get(combo[1]), y=base::get(combo[2]))) +
geom_point() +
labs(x=combo[1],
y=combo[2],
title=paste("Loop Method:", paste(combo, collapse=" vs ")))
}
```
When using a for loop in a code chunk with Markdown files, you need to explicitly print() the plot. So, the following code would not work:
for (i in length(x)) {
ggplot(...)
}
You need to convert to something like this:
for (i in length(x)) {
p <- ggplot(...)
print(p)
}

Controlling the size and number of graphs per pdf page generated by ggplot loop in R markdown

I would like to generate a pdf document, using R markdown, to display a series of plots made using ggplot in a for loop. Is it possible to control number of plots on each page so there is, for example, a 2 X 2 grid of plots per page?
I'd like to maintain the flexibility so that I can change the total number of graphs, so that it splits across the appropriate number of pages.
My attempt using ggplot2 and gridExtra packages is below, but I can't control the number of graphs per page, it seems to want to squeeze them on to a sinlge page only. I've tried changing the ncol,nrow,heights,widths arguments in grid.arrange but it doesn't seem to help.
---
title: "ggplot Layout"
output: pdf_document
---
```{r,figure2 fig.height=8, fig.width=6,echo=FALSE,message=FALSE}
library(ggplot2)
library(gridExtra)
graphlist<-list()
count <- 1
colnums<-c(1,5,6,7,8,9,10)
for (i in colnums) {
plot.x.name<-names(diamonds[i])
p <- ggplot(data=diamonds,aes_string(x = plot.x.name)) + geom_histogram()
graphlist[[count]]<-p
count <- count+1
}
do.call("grid.arrange",c(graphlist,ncol=2))
```
The type of thing I'm looking for is demonstrated by this code (adapted from
http://kbroman.github.io/knitr_knutshell/pages/figs_tables.html), but this doesn't work with ggplot, unfortunately.
---
title: "Example Layout"
output: pdf_document
---
```{r bunch_o_figs,fig.height=8, fig.width=6, message=FALSE,echo=FALSE}
n <- 100
x <- rnorm(n)
par(mfrow=c(2,2), las=1)
for(i in 1:20) {
y <- i*x + rnorm(n)
plot(x, y, main=i)
}
``
You could try marrangeGrob
---
title: "ggplot Layout"
output: pdf_document
---
```{r figure2 , fig.height=8, fig.width=6,echo=FALSE,message=FALSE}
library(ggplot2)
library(gridExtra)
graphlist <- replicate(10, qplot(1,1), simplify = FALSE)
do.call("marrangeGrob",c(graphlist,ncol=2,nrow=2))
```

Resources