user2478159
user2478159

Reputation: 133

Conditional output plot

Suppose I have a conditional panel

fluidRow(column(12,selectInput("models", label = "Models",choices =list("choice 1"=1,"choice 2"=2))))    

tabsetPanel(tabPanel(strong("plots"),
                             plotOutput("plot 1"),
                             plotOutput("plot 2")))

Now, according to some select input value, I want to show plot 1 or plot 2. Is there a way to to that in a shiny app ?

Upvotes: 0

Views: 259

Answers (1)

Christoph Wolk
Christoph Wolk

Reputation: 1758

First version, with selection in the render:

library(shiny)


ui <- fluidPage(fluidRow(column(12,selectInput("models", label = "Models",choices =list("A-Plots"=1,"B-Plots"=2)))),    

tabsetPanel(tabPanel(strong("plots"),
                     lapply(1:5, function(i) plotOutput(paste0("plot", i))))))

server <- function(session, input, output) {

 plotsA <- lapply(1:5, function(x) function(y) (plot(1:10, main=paste("Plot A", x))))

 plotsB <- lapply(1:5, function(x) function(y) (plot(1:10, main=paste("Plot B", x))))

 for (i in 1:5) local({
   my_i <- i
   output[[paste0("plot", my_i)]] <- renderPlot({
     switch(input$models, "1"=plotsA, "2"=plotsB)[[my_i]]()})
 })}

shinyApp(ui = ui, server = server)

Version 2 with conditionalPanel:

library(shiny)

ui <- fluidPage(fluidRow(column(12,selectInput(
  "models", label = "Models", choices =list("A-Plots"=1,"B-Plots"=2)))),    

tabsetPanel(tabPanel(strong("plots"),
                     conditionalPanel("input.models==1",
                       lapply(1:5, function(i) plotOutput(paste0("plot", i)))),
                     conditionalPanel("input.models==2",
                       lapply(6:10, function(i) plotOutput(paste0("plot", i)))))))

server <- function(session, input, output) {

  plotsA <- lapply(1:5, function(x) function(y) (plot(1:10, main=paste("Plot A", x))))

  plotsB <- lapply(1:5, function(x) function(y) (plot(1:10, main=paste("Plot B", x))))

  for (i in 1:5) local({
    my_i <- i
    output[[paste0("plot", my_i)]] <- renderPlot({plotsA[[my_i]]()})
  })

  for (i in 6:10) local({
    my_i <- i
    output[[paste0("plot", my_i)]] <- renderPlot({plotsB[[my_i-5]]()})
  })

}

shinyApp(ui = ui, server = server)

Third option, with uiOutput:

library(shiny)


ui <- fluidPage(fluidRow(column(12,selectInput(
  "models", label = "Models", choices =list("A-Plots"=1,"B-Plots"=2)))),    

tabsetPanel(tabPanel(strong("plots"),
                     uiOutput("plots"))))

server <- function(session, input, output) {

  plotsA <- lapply(1:5, function(x) function(y) (plot(1:10, main=paste("Plot A", x))))

  plotsB <- lapply(1:5, function(x) function(y) (plot(1:10, main=paste("Plot B", x))))

  output$plots <- renderUI(lapply(switch(input$models, "1"=1:5, "2"=6:10),
                                  function(y) plotOutput(paste0("plot", y))))

  for (i in 1:5) local({
    my_i <- i
    output[[paste0("plot", my_i)]] <- renderPlot({plotsA[[my_i]]()})
  })

  for (i in 6:10) local({
    my_i <- i
    output[[paste0("plot", my_i)]] <- renderPlot({plotsB[[my_i-5]]()})
  })

}

shinyApp(ui = ui, server = server)

In all cases, the plot should only be prepared if you are actually displaying that plot.

Upvotes: 1

Related Questions