Last active
February 2, 2025 16:41
-
-
Save wch/5436415 to your computer and use it in GitHub Desktop.
Shiny example app with dynamic number of plots
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
max_plots <- 5 | |
ui <- fluidPage( | |
headerPanel("Dynamic number of plots"), | |
sidebarPanel( | |
sliderInput("n", "Number of plots", value=1, min=1, max=5) | |
), | |
mainPanel( | |
# This is the dynamic UI for the plots | |
uiOutput("plots") | |
) | |
) | |
server <- function(input, output) { | |
# Insert the right number of plot output objects into the web page | |
output$plots <- renderUI({ | |
plot_output_list <- lapply(1:input$n, function(i) { | |
plotname <- paste("plot", i, sep="") | |
plotOutput(plotname, height = 280, width = 250) | |
}) | |
# Convert the list to a tagList - this is necessary for the list of items | |
# to display properly. | |
do.call(tagList, plot_output_list) | |
}) | |
# Call renderPlot for each one. Plots are only actually generated when they | |
# are visible on the web page. | |
for (i in 1:max_plots) { | |
# Need local so that each item gets its own number. Without it, the value | |
# of i in the renderPlot() will be the same across all instances, because | |
# of when the expression is evaluated. | |
local({ | |
my_i <- i | |
plotname <- paste("plot", my_i, sep="") | |
output[[plotname]] <- renderPlot({ | |
plot(1:my_i, 1:my_i, | |
xlim = c(1, max_plots), | |
ylim = c(1, max_plots), | |
main = paste("1:", my_i, ". n is ", input$n, sep = "") | |
) | |
}) | |
}) | |
} | |
} | |
shinyApp(ui, server) |
I wanted to add another use case to this excellent gist. In my case I wanted to generate a dynamic number of graphs based on the factor levels of a column from a user input file. See also https://stackoverflow.com/questions/75250661/generate-dynamic-number-of-plots-based-on-factor-levels-of-user-input-file/75251212#75251212
library(shiny)
library(data.table)
library(ggplot2)
library(dplyr)
ui <- fluidPage(
headerPanel("Dynamic number of plots"),
sidebarPanel(
fileInput("fileIn",
"Load input file",
multiple = F)
),
mainPanel(
uiOutput("plot1")
)
)
server <- function(input, output) {
getData <- reactive({
req(input$fileIn)
dataIn <- as.data.frame(fread(input$fileIn$datapath))
dataIn$plotGroup <- make.names(dataIn$plotGroup)
return(dataIn)
})
output$plot1 <- renderUI({
plotOutputList <- lapply(unique(getData()$plotGroup),
function(i){
plotname <- paste("plot", i, sep = "_")
plotOutput(plotname)
})
do.call(tagList, plotOutputList)
})
observe({
for(i in unique(getData()$plotGroup)){
local({
iCurrent <- i
plotname <- paste("plot", iCurrent, sep = "_")
output[[plotname]] <- renderPlot({
getData() %>%
filter(plotGroup == iCurrent) %>%
ggplot(aes(x = xGroup, y = yVar)) +
geom_point()
})
})
}})
}
shinyApp(ui, server)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @INTELLIGENTICA ,
The app then needs to then set to behave in a specific way only and lose some of its dynamicity. Or, Have tabs/select drop down for each of the columns in the uploaded data.frame to group/color by and thereby show the legend for.
To download all the generated plots with one click, there are multiple ways to do it -
Each of these is doable since the dynamic plots produced are available as individual list items in
plot_output_list