I have a variable list of plots that does not depend on the number of plots a user selects. Rather, they input data, and given their data structure, I return the appropriate number of plots in a list. The user is unaware of the appropriate number of plots - my code figures it out for them. As such, the number of objects in the list is not an input that they select.
I've successfully used lapply to generate multiple plots in RStudio, but only the last plot appears in my Shiny App. I think I've seen this discussed on some traditional shiny apps, but I'm having trouble translating it to flexdashboard/RMD.
I've included a simple reprex below. The number of objects in iris_list is variable. I use lapply to bind together two plots from each object/dataset in the list, and patchwork to add a shared legend (not included in the reprex). How can I get all object in the list to appear in my app? I get the impression that I need multiple renderPlots and an Observe statement.
---
title: "my app"
runtime: shiny
output:
flexdashboard::flex_dashboard:
orientation: columns
source_code: embed
theme: flatly
always_allow_html: yes
---
### Plots
```{r chunk}
renderPlot({
iris_list<- list(iris,iris)
p1 <- map(iris_list,~ggplot(data=.x,aes(x=Sepal.Length))+geom_histogram())
p2 <- map(iris_list,~ggplot(data=.x,aes(x=Petal.Length))+geom_histogram())
plots_combined <- lapply(seq(length(iris_list)),function(x) c(p1[x],p2[x]))
lapply(seq(length(plots_combined)), function(x) wrap_plots(plots_combined[[x]])+
plot_annotation(title=paste("plot",x)))
})
```
The answer can be found here: R Markdown Shiny renderPlot list of plots from lapply. I misread it earlier, but the answer was right in front of me the whole time.
The trick is to change the renderPlot
to reactive
, put it into an object, and then add the renderUI
and the observe
statements. This works perfectly in flexdashboard. The width
and height
of the plot go after the renderPlot
statement as they normally would, e.g.
renderPlot({
}, width=900,height = 325)