Problem:
I have a large amount of data I am trying visualize for my users. This may be several hundred plots. In the app currently I am making ggplot2 small multiples using facet_wrap and that's working pretty well up to around 100 plots. However, I want the user to be able to export all of the plots as a record of what they have done and also to be able to visualize all of the plots, not just the first 100. I'm not too worried how it's formatted (ie as a ggforce::facet_wrap_paginate() or as completely separate plots as below).
I have tried several approaches I found on stack-overflow but nothing seems to be working
The following code works if I try and export the plots in R but I can't get the download in shiny to work.
library(shiny)
library(ggplot2)
ui <- fluidPage(
downloadButton("plot_download", "Download all plots"),
plotOutput("facet_plot")
)
server <- function(input, output) {
data <- reactive({
data.frame(group = rep(LETTERS, each = 100),
x = runif(n = 20, min = 10, max = 15),
y = runif(n = 20, min = 100, max = 150))
})
output$facet_plot <- renderPlot({
data() |>
ggplot(aes(x,y))
geom_point()
facet_wrap(vars(group))
})
output$plot_download <- downloadHandler(
filename = function() {
paste0(Sys.Date(), "_plot.pdf")
},
content = function(file) {
pdf(file)
data() |>
split(by="group") |>
lapply(function(data) {
gg <- data |>
ggplot(aes(x,y))
geom_point()
})
dev.off()
}
)
}
shinyApp(ui = ui, server = server)
CodePudding user response:
Instead of calling the pdf function, you can use ggsave function. It will save the output in the desired format with parameters like width, height, dpi, and units.
You can find the documentation here.
The code will look like this:
library(shiny)
library(ggplot2)
ui <- fluidPage(
downloadButton("plot_download", "Download all plots"),
plotOutput("facet_plot")
)
server <- function(input, output) {
data <- reactive({
data.frame(group = rep(LETTERS, each = 100),
x = runif(n = 20, min = 10, max = 15),
y = runif(n = 20, min = 100, max = 150))
})
output$facet_plot <- renderPlot({
data() %>%
ggplot(aes(x,y))
geom_point()
facet_wrap(vars(group))
})
output$plot_download <- downloadHandler(
filename = function() {
paste0(Sys.Date(), "_plot.pdf", sep = '')
},
content = function(file) {
ggsave(file, data() %>% ggplot(aes(x, y)) geom_point() facet_wrap(~group), dpi = 300)
}
)
}
shinyApp(ui = ui, server = server)
P.S: I've changed a few things here and there in your code. The code to save the plot should work with your previous code.
EDIT
In order to scale the solution according to your needs, I made a few changes to the code.
There's a package called ggforce. You can find about it here. It will help you save the plots from facet_wrap as individual graphs on single pages or in rows and column-wise fashion.
Here's how the code will look like:
filename = function() {
paste0(Sys.Date(), "_plot.pdf", sep = '')
},
content = function(file) {
pdf(file)
#ggsave(file, data() %>% ggplot(aes(x, y)) geom_point() facet_wrap(~group), dpi = 300)
for(i in 1:length(unique(data()$group))) {
print(data() %>% ggplot(aes(x, y)) geom_point()
facet_wrap_paginate(~group, ncol = 1, nrow = 1, page = i))
}
dev.off()
}
Notice that, I'm using for group based on your sample data. You can change it according to your needs. facet_wrap_paginate is the function you require here. You can specify the number of columns and rows of plots you want to save on each page with it.
