I'm looking for an elegant solution to keep plots with variable height cached in memory. In my use case there are currently about 100 different plots, so I could simply pre-generate them and load at startup but I'll rather avoid that since (extra work and scales badly). I would also rather avoid having to load any external packages apart from shiny and ggplot2.
The problem is:
When I use bindCache() on renderPlot() its plot_height() seems to be ignored.
library(shiny)
ui <- fluidPage(
selectInput("x_var", "X:", c("cyl", "carb")),
plotOutput("plot")
)
server <- function(input, output, session) {
plot_height <- reactive(200 + 50 * length(unique(mtcars[[input$x_var]])))
make_plot <- function(col) {
groups <- factor(mtcars[[col]])
boxplot(mtcars$mpg ~ groups, horizontal = TRUE)
}
output$plot <- renderPlot(expr = make_plot(input$x_var), height = plot_height) #|> bindCache(input$x_var)
}
shinyApp(ui, server)
As mentioned by @MichaelDewar in the comments, when bindCache() is used with renderPlot(), the height and width passed to the original renderPlot() are ignored, from help(bindCache), section Caching with renderPlot():
When
bindCache()is used withrenderPlot(), the height and width passed to the originalrenderPlot()are ignored. They are superseded bysizePolicyargument passed tobindCache. [...]sizePolicymust be a function that takes a two-element numeric vector as input, representing the width and height [...]
As stated, we can pass a custom function to the sizePolicy parameter, which takes into account the plot_height reactive. For this to work please note, that we also have to pass height = 100% to the plotOutput otherwise the hight of the img-tag's parent div will be set to its default of 400 px:
library(shiny)
ui <- fluidPage(
selectInput("x_var", "X:", c("cyl", "carb")),
plotOutput("plot", width = "100%", height = "100%")
)
server <- function(input, output, session) {
plot_height <- reactive(200 + 50 * length(unique(mtcars[[input$x_var]])))
make_plot <- function(col) {
groups <- factor(mtcars[[col]])
boxplot(mtcars$mpg ~ groups, horizontal = TRUE)
}
output$plot <- renderPlot(
expr = make_plot(input$x_var)
) |>
bindCache(input$x_var, sizePolicy = function(x) {
return(c(x[1L], plot_height()))
})
}
shinyApp(ui, server)

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With