The main goal of my Shiny app is to display large amounts of data through (interactive) ggplots. With sufficient data, the time it takes to display the plots can run up to ~10 seconds, and I would like to display a progress bar to provide feedback.
I've tried both withProgress and winProgressBar, but neither reflect the time it takes for the ggplots to appear: both progress bars disappear long before the actual plots are shown.
So my question is: how do I implement (any type of) progress bar to reflect the time it takes for the ggplots to appear on screen?
library(shiny)
library(ggplot2)
library(dplyr)
ui = fluidPage(
mainPanel(
uiOutput("plots")
)
)
server = function(input, output) {
#list of things I want to plot, which will be split over column wt
plotlist = sort(unique(mtcars$wt))[1:4]
observe({
pb = winProgressBar( #test 1: winProgressBar
title = 'observe', #test 1: winProgressBar
label = 'plotting' #test 1: winProgressBar
) #test 1: winProgressBar
message({ #test 1: winProgressBar
withProgress(message = 'ggplotting', value = 0, { #test 2: withProgress
for (i in plotlist) local({
nm <- i
temp.data <- filter(mtcars, wt == plotlist[nm])
plotAname <- paste0("plotA", nm)
output[[plotAname]] <- renderPlot(ggplot(temp.data, aes(x = mpg, y= cyl)) + geom_point())
plotBname <- paste0("plotB", nm)
output[[plotBname]] <- renderPlot(ggplot(temp.data, aes(x = mpg, y= drat)) + geom_point())
plotCname <- paste0("plotC", nm)
output[[plotCname]] <- renderPlot(ggplot(temp.data, aes(x = mpg, y= disp)) + geom_point())
plotDname <- paste0("plotD", nm)
output[[plotDname]] <- renderPlot(ggplot(temp.data, aes(x = mpg, y= hp)) + geom_point())
setWinProgressBar(pb, value = nm/10) #test 1: winProgressBar
incProgress(1/(length(plotlist))) #test 2: withProgress
}) #end of for()
}) #end of withProgress #test 2: withProgress
close(pb) #test 1: winProgressBar
}) #end of message #test 1: winProgressBar
}) #end of observe
output$plots <- renderUI({
withProgress(message = 'rendering', value = 0, { #test 3: withProgress
plot_output_list <- lapply(plotlist, function(i) {
incProgress(1/(length(plotlist))) #test 3: withProgress
#encompass everything in a div because lapply can only returns a single result per loop cycle.
div(style = "padding: 0px; margin: 0px;",
div(style = "position:relative; margin-bottom: -5px; padding: 0px;",
plotOutput(paste0("plotA", i))
),
div(style = "position:relative; margin-bottom: -5px; padding: 0px;",
plotOutput(paste0("plotB", i))
),
div(style = "position:relative; margin-bottom: -5px; padding: 0px;",
plotOutput(paste0("plotC", i))
),
plotOutput(paste0("plotD", i))
)
}) #end of lapply
}) #end of withProgress #test 3: withProgress
}) #end of output$plots
}
shinyApp(ui = ui, server = server)
This example takes about ~4 seconds to display its plots. All three test progress bars have finished after about ~1 second.
Thanks for taking the time to go through this! If I can provide any clarification, please let me know.