Multiple Plot outputs from a function in rmarkdown - r

I have a function that produces 2 chart objects and I'd like to use this function in an rmarkdown file and knit it so that I get an HTML report. The problem I'm facing is that when I use this function, I get an output that looks something like this:
Here "Plot1" and "Plot2" are the actual plots that get rendered. What changes to I need to make so that I only get the following?
Plot1
Plot2
Here is the code chunk from my R-markdown file.
```{r OverallGRP106_trended_fav, echo=FALSE, fig.align="center", message=FALSE, warning=FALSE, paged.print=TRUE}
trended_fav(psc_surv,"Overall","GRP106")
```
The return statement of function "trended_fav" is as follows:
return(list(plot(p4), plot(p1)))

I think you'll be ok if you assign the function's output to a variable and then call up the element of the variable separately, like so:
---
output: html_document
---
```{r setup, include=FALSE}
library(ggplot2)
trended_fav <- function() {
p4 <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p1 <- ggplot(txhousing, aes(year, median)) + geom_point()
plot_list <- list(p4,p1)
return(plot_list)
}
a <- trended_fav()
```
## First report
Here it is:
```{r}
a[1]
```
## Second report
This one is even better:
```{r}
a[2]
```

Related

rmarkdown/purrr: remove list indices between plots

When I knit a document containing multiple plots obtained through purrr:map function, I get text slides in between each plot slide containing unwanted list index information (see image slides 2, 4, and 6). I'd like to remove these and just have plots.
I've tried results = "hide" and results = FALSE in the header.
These just return one plot instead of many, AND the text is still
there.
I've tried adding invisible() around my code as recommended
here. I don't see a difference.
How can I remove these and just have three slides with the three plots with no text?
---
title: "Reprex"
output: powerpoint_presentation
---
```{r include=FALSE}
library(tidyverse)
```
```{r echo=FALSE, results = FALSE}
ys <- c("mpg","cyl","disp")
ys %>% map(function(y)
invisible(ggplot(mtcars, aes(hp)) + geom_point(aes_string(y=y))))
```
Try this:
To suppress the console output use purrr::walk instead of map. See e.g. https://chrisbeeley.net/?p=1198
To get each plot printed on a separate slide use results='asis' and add two newlines via cat('\n\n') after each plot.
---
title: "Reprex"
output: powerpoint_presentation
---
```{r include=FALSE}
library(tidyverse)
```
```{r echo=FALSE, results='asis'}
ys <- c("mpg","cyl","disp")
walk(ys, function(y) {
p <- ggplot(mtcars, aes(hp)) + geom_point(aes_string(y=y))
print(p)
cat('\n\n')
})
```

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)
}

How to embed plots into a tab in RMarkdown in a procedural fashion?

I can embed plots using just RMarkdown's {.tabset}
#### Heading {.tabset}
##### Subheading 1
```{r, echo=F}
df[[1]]
```
This produces individual tabs with the specified graphs (df is a list of graphs, calling df[[i]] produces a graph) in the preview pane (renders all the graphs inline in RStudio).
And I can generate just the tabs using a for loop.
```{r, results='asis', echo = FALSE}
for (i in 1:length(gg0)) {
cat("##### ",q$Subheading[i],"\n")
}
```
And this produces the desired output - the tabs with the names in the Subheading column.
However, I am stuck in trying to generate the graphs themselves using the for loop similar to how I did when I coded it manually.
Extending the above, I tried to generate the markdown that produced the initial output but the plot fails to generate (both in the inline markdown and preview).
```{r, results='asis', echo = FALSE}
for (i in 1:length(gg0)) {
cat("##### ",q$Subheading[i],"\n")
cat('```{r, echo=F} \n')
cat("gg0[[",i,"]]\n")
cat('``` \n')
}
```
Maybe I am missing a finer point regarding markdown? I have tried various patterns using cat (and even without)
I would prefer a RMarkdown solution but other solutions are just as welcome.
I played around a little and found a solution. You have to use print within the asis code chunk...
```{r}
library(ggplot2)
gg0 <- list()
gg0[[1]] <- ggplot(mtcars, aes(mpg, hp)) + geom_point()
gg0[[2]] <- ggplot(mtcars, aes(mpg, disp)) + geom_point()
gg0[[3]] <- ggplot(mtcars, aes(mpg, drat)) + geom_point()
headings <- c('hp','disp','drat')
```
#### Heading {.tabset}
```{r, results='asis', echo = FALSE}
for (i in 1:length(gg0)) {
cat("##### ",headings[i],"\n")
print(gg0[[i]])
cat('\n\n')
}
```
As an explanation, the cat command together with results='asis' produces the markdown code for a lower level headline and prints the ggplot graph afterwards. Since we used `{.tabset} in the parent headline, it creates the plots in separate tabs.
Adding both plot.new(), dev.off() inside the for loop solves the problem of adding all the figures in the last tab. See the complete solution here.

Print RMarkdown captions from a loop

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")
})
```

Printing plots generated in a function using R Markdown in RStudio

I am trying to use the R-Markdown feature in R Studio where I was trying to print plots which are generated inside a function. This is a basic run down example of what I am trying to do.
**Test printing plots generated in a function**
================================================
``` {r fig.width=8, fig.height=4, warning=FALSE, eval=TRUE, message=FALSE, tidy=TRUE, dev='png', echo=FALSE, fig.show='hold', fig.align='center'}
dat <- data.frame(x=c(1:10),y=c(11:20),z=c(21:30),name=rep(c("a","b"),each=5))
library(ggplot2)
ex <- function(data){
plot(data[,1],data[,2])
plot(data[,1],data[,3])
}
for (i in 1:10){
t1 <- rbind(i,ex(dat))
}
t1
```
Those testing this code, please make sure to save it as ".Rmd" file and then run the knithtml() in RStudio toolbar. This code above works absolutely fine with the kind of html output I desire. However when I replace the base plotting function by ggplot based code, I cannot get the knithtml() to produce the ggplot output of the 10 plots that I got like before. The base plot code above is now replaced by the following code
p1 <- ggplot(data=data, aes(x=data[,1],y=data[,2]))
p1 <- p1+geom_point()
p1
Am I missing something very simple here.
VJ
There are two problems in your code:
ggplot doesn't recognize the data x and y data, bacause it works inside the data environment. You should give it the column names directly.
The code in yur loop doesn't make sense. You can't mix a plot with an index... (the reason it works with the base plot is through a side-effect) I've replaced it with the simple plot command.
The following will work:
**Test printing plots generated in a function**
================================================
``` {r fig.width=8, fig.height=4, warning=FALSE, eval=TRUE, message=FALSE, tidy=TRUE, dev='png', echo=FALSE, fig.show='hold', fig.align='center'}
dat <- data.frame(x=c(1:10),y=c(11:20),z=c(21:30),name=rep(c("a","b"),each=5))
library(ggplot2)
ex <- function(data){
p1 <- ggplot(data=data, aes(x=x,y=y))
p1 <- p1+geom_point()
return(p1)
}
for (i in 1:2){
plot(ex(dat))
}
```

Resources