Conditional selection in a shiny renderUI

Hi,

I'm working on a shiny App that has 3 figure display options for the data it uses.
For two of these options, the usee has to select a single additional input from a list, but the third I'd like the user to select two additional inputs. I know that these selections can be implemented in renderUI in the server part. However, what I currently have in the renderUI is a single option for selection depending on the selected figure display option, and I don't know how to add the additional one for the third display option.

Here's my example:

suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(plotly))
suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(shiny))


#data.frames to be used in the server
set.seed(1)
coordinate.df <- data.frame(coordinate_id = paste0("c", 1:1000),x = rnorm(1000), y = rnorm(1000), type = sample(LETTERS[1:4], 1000, replace = T), sex = sample(c("F","M"), 1000, replace = T), age = sample(c("Y","O"), 1000, replace = T), stringsAsFactors = F)
feature.df <- data.frame(coordinate_id = rep(paste0("c", 1:1000), 10), feature_id = rep(paste0("f", 1:10), 1000), value = rnorm(10*1000), stringsAsFactors = F)

#options to be used for subsetting point.df not on the fly
types <- c("all",unique(coordinate.df$type))
type.choices <- 1:length(types)
names(type.choices) <- types

sexes <- c("all",unique(coordinate.df$sex))
sex.choices <- 1:length(sexes)
names(sex.choices) <- sexes

ages <- c("all",unique(coordinate.df$age))
age.choices <- 1:length(ages)
names(age.choices) <- ages

color.code.groups <- c("type","sex","age")
feature.color.vec <- c("lightgray","darkred")

plot.type.choices <- c("Group Coordinate Plot","Feature Coordinate Plot","Feature Distribution Plot")

server <- function(input, output)
{
  chosen.types <- reactive({
    validate(
      need(input$types.choice != "",'Please choose at least one of the type checkboxes')
    )
    types.choice <- input$types.choice
    if("all" %in% types.choice) types.choice <- types[-which(types == "all")]
    types.choice
  })

  chosen.sexes <- reactive({
    validate(
      need(input$sexes.choice != "",'Please choose at least one of the sex checkboxes')
    )
    sexes.choice <- input$sexes.choice
    if("all" %in% sexes.choice) sexes.choice <- sexes[-which(sexes == "all")]
    sexes.choice
  })

  chosen.ages <- reactive({
    validate(
      need(input$ages.choice != "",'Please choose at least one of the age checkboxes')
    )
    ages.choice <- input$ages.choice
    if("all" %in% ages.choice) ages.choice <- ages[-which(ages == "all")]
    ages.choice
  })
  
  output$selection <- renderUI({
    if(input$plotType == "Group Coordinate Plot"){
      selectInput("selection", "Select Group to Color-Code by", choices = color.code.groups)
    } else if(input$plotType == "Feature Coordinate Plot"){
      selectInput("selection", "Select Feature to Display", choices = unique(feature.df$feature_id))
    } else if(input$plotType == "Feature Distribution Plot"){
      selectInput("selection", "Select Feature to Display", choices = unique(feature.df$feature_id))
    }
  })

  group.coordinate.plot <- reactive({
    if(!is.null(input$selection)){
      plot.chosen.types <- chosen.types()
      plot.chosen.sexes <- chosen.sexes()
      plot.chosen.ages <- chosen.ages()
      if(input$plotType == "Group Coordinate Plot"){
        plot.df <- suppressWarnings(coordinate.df %>%
                                      dplyr::filter(type %in% plot.chosen.types & sex %in% plot.chosen.sexes & age %in% plot.chosen.ages) %>%
                                      dplyr::mutate(hover.text = paste0("coordinate_id: ",coordinate_id,"\n","type: ",type,"\n","sex: ",sex,"\n","age: ",age)))
        plot.df$group <- plot.df[,input$selection]
        plot.df$group <- factor(plot.df$group)
        group.coordinate.plot <- suppressWarnings(plotly::plot_ly(marker=list(size=3),type='scatter',mode="markers",color=plot.df$group,x=plot.df$x,y=plot.df$y,text=plot.df$hover.text,hoverinfo="text") %>%
                                                    plotly::layout(xaxis=list(zeroline=F,showticklabels=F,showgrid=F),yaxis=list(zeroline=F,showticklabels=F,showgrid=F),legend=list(itemsizing='constant')))
      }
    }
    group.coordinate.plot
  })

  feature.coordinate.plot <- reactive({
    if(!is.null(input$selection)){
      plot.chosen.types <- chosen.types()
      plot.chosen.sexes <- chosen.sexes()
      plot.chosen.ages <- chosen.ages()
      if(input$plotType == "Feature Coordinate Plot"){
        feature.id <- input$selection
        plot.title <- feature.id
        plot.df <- suppressWarnings(feature.df %>%
                                      dplyr::filter(feature_id == feature.id) %>%
                                      dplyr::left_join(coordinate.df,by = c("coordinate_id"="coordinate_id")) %>%
                                      dplyr::mutate(hover.text = paste0("coordinate_id: ",coordinate_id,"\n","type: ",type,"\n","sex: ",sex,"\n","age: ",age,"\n","value: ",value)))
        feature.coordinate.plot <- suppressWarnings(plotly::plot_ly(marker=list(size=3),type='scatter',mode="markers",color=plot.df$value,x=plot.df$x,y=plot.df$y,text=plot.df$hover.text,hoverinfo="text",showlegend=F,colors=colorRamp(feature.color.vec)) %>%
                                        plotly::layout(title=plot.title,xaxis=list(zeroline=F,showticklabels=F,showgrid=F),yaxis=list(zeroline=F,showticklabels=F,showgrid=F)) %>%
                                        plotly::colorbar(limits=c(min(plot.df$value,na.rm=T),max(plot.df$value,na.rm=T)),len=0.4,title="Value"))
        
      }
    }
    feature.coordinate.plot
  })
  
  feature.distribution.plot <- reactive({
    if(!is.null(input$selection)){
      plot.chosen.types <- chosen.types()
      plot.chosen.sexes <- chosen.sexes()
      plot.chosen.ages <- chosen.ages()
      if(input$plotType == "Feature Distribution Plot"){
        feature.id <- input$selection
        plot.title <- feature.id
        plot.df <- suppressWarnings(feature.df %>%
                                      dplyr::filter(feature_id == feature.id) %>%
                                      dplyr::left_join(coordinate.df,by = c("coordinate_id"="coordinate_id")) %>%
                                      dplyr::mutate(hover.text = paste0("coordinate_id: ",coordinate_id,"\n","type: ",type,"\n","sex: ",sex,"\n","age: ",age,"\n","value: ",value)))
        density.df <- do.call(rbind,lapply(sort(unique(plot.df$type)),function(t)
          ggplot2::ggplot_build(ggplot2::ggplot(plot.df %>% dplyr::filter(type == t),ggplot2::aes(x=value))+ggplot2::geom_density(adjust=1,colour="#A9A9A9"))$data[[1]] %>%
            dplyr::select(x,y) %>% dplyr::mutate(type = t))) %>% dplyr::left_join(dplyr::select(coordinate.df,type) %>% unique())
        density.df$type <- factor(density.df$type)
        feature.distribution.plot <- suppressWarnings(plotly::plot_ly(x=density.df$x,y=density.df$y,type='scatter',mode='lines',color=density.df$type) %>%
                                                        plotly::layout(title=plot.title,xaxis=list(title="Value",zeroline=F),yaxis=list(title="Density",zeroline=F)) %>%
                                                        plotly::add_annotations(text="type",xref="paper",yref="paper",x=1.02,xanchor="left",y=1.02,yanchor="top",legendtitle=T,showarrow=F))
      }
    }
    feature.distribution.plot
  })
 
  output$outPlot <- plotly::renderPlotly({
    if(input$plotType == "Group Coordinate Plot"){
      group.coordinate.plot()
    } else if(input$plotType == "Feature Coordinate Plot"){
      feature.coordinate.plot()
    } else if(input$plotType == "Feature Distribution Plot"){
      feature.distribution.plot()
    }
  })
}

ui <- fluidPage(
  
  # App title ----
  titlePanel("Results Explorer"),
  
  # Sidebar layout with a input and output definitions ----
  sidebarLayout(
    # Sidebar panel for inputs ----
    sidebarPanel(
      
      ## custom CSS for 3 column layout (used below for mechanics filter options)
      tags$head(
        tags$style(HTML(".multicol {-webkit-column-count: 3; /* Chrome, Safari, Opera */-moz-column-count: 3; /* Firefox */column-count: 3;}"))),
      ## use the css, assuming your long list of vars comes from global.R
      wellPanel(tags$div(class="multicol",checkboxGroupInput("types.choice", "Type",choices = names(type.choices),selected="all"))),
      wellPanel(tags$div(class="multicol",checkboxGroupInput("sexes.choice", "Sex",choices = names(sex.choices),selected="all"))),
      wellPanel(tags$div(class="multicol",checkboxGroupInput("ages.choice", "Age",choices = names(age.choices),selected="all"))),

      # select plot type
      selectInput("plotType", "Plot Type", choices = plot.type.choices),

      uiOutput("selection")
      
    ),
    
    # Main panel for displaying outputs ----
    mainPanel(
      # The plot is called out.plot and will be created in ShinyServer part
      plotly::plotlyOutput("outPlot")
    )
  )
)

shinyApp(ui = ui, server = server)

The "Feature Distribution Plot" input$plotType is the display option to which I would like to add the additional user input selection (which will be between the density plot - the current implemented option, or a violin plot).

Any idea how do I add this?

https://www.diffchecker.com/5VnF9OFF

You need to provide a second selection

else if(input$plotType == "Feature Distribution Plot"){	
selectInput("selection", "Select Feature to Display", choices = unique(feature.df$feature_id))	
}
else if(input$plotType == "Feature Distribution Plot"){
tagList(selectInput("selection", "Select Feature to Display", choices = unique(feature.df$feature_id)),
selectInput("secondselection", "Select Plot to Display", choices = c("Density","Violin")))
}

then use it to decide what to plot

feature.distribution.plot <- reactive({	
if(!is.null(input$selection)){	
plot.chosen.types <- chosen.types()	
plot.chosen.sexes <- chosen.sexes()	
plot.chosen.ages <- chosen.ages()	
if(input$plotType == "Feature Distribution Plot"){	
feature.id <- input$selection	
plot.title <- feature.id	
plot.df <- suppressWarnings(feature.df %>%	
dplyr::filter(feature_id == feature.id) %>%	
dplyr::left_join(coordinate.df,by = c("coordinate_id"="coordinate_id")) %>%	
dplyr::mutate(hover.text = paste0("coordinate_id: ",coordinate_id,"\n","type: ",type,"\n","sex: ",sex,"\n","age: ",age,"\n","value: ",value)))	
density.df <- do.call(rbind,lapply(sort(unique(plot.df$type)),function(t)	
ggplot2::ggplot_build(ggplot2::ggplot(plot.df %>% dplyr::filter(type == t),ggplot2::aes(x=value))+ggplot2::geom_density(adjust=1,colour="#A9A9A9"))$data[[1]] %>%	
dplyr::select(x,y) %>% dplyr::mutate(type = t))) %>% dplyr::left_join(dplyr::select(coordinate.df,type) %>% unique())	
density.df$type <- factor(density.df$type)	
feature.distribution.plot <- suppressWarnings(plotly::plot_ly(x=density.df$x,y=density.df$y,type='scatter',mode='lines',color=density.df$type) %>%	
plotly::layout(title=plot.title,xaxis=list(title="Value",zeroline=F),yaxis=list(title="Density",zeroline=F)) %>%	
plotly::add_annotations(text="type",xref="paper",yref="paper",x=1.02,xanchor="left",y=1.02,yanchor="top",legendtitle=T,showarrow=F))	
}	
}	
feature.distribution.plot	
})
feature.distribution.plot <- reactive({
if(!is.null(input$selection)){
plot.chosen.types <- chosen.types()
plot.chosen.sexes <- chosen.sexes()
plot.chosen.ages <- chosen.ages()
if(input$plotType == "Feature Distribution Plot"){
if(input$secondselection=='Density'){
feature.id <- input$selection
plot.title <- feature.id
plot.df <- suppressWarnings(feature.df %>%
dplyr::filter(feature_id == feature.id) %>%
dplyr::left_join(coordinate.df,by = c("coordinate_id"="coordinate_id")) %>%
dplyr::mutate(hover.text = paste0("coordinate_id: ",coordinate_id,"\n","type: ",type,"\n","sex: ",sex,"\n","age: ",age,"\n","value: ",value)))
density.df <- do.call(rbind,lapply(sort(unique(plot.df$type)),function(t)
ggplot2::ggplot_build(ggplot2::ggplot(plot.df %>% dplyr::filter(type == t),ggplot2::aes(x=value))+ggplot2::geom_density(adjust=1,colour="#A9A9A9"))$data[[1]] %>%
dplyr::select(x,y) %>% dplyr::mutate(type = t))) %>% dplyr::left_join(dplyr::select(coordinate.df,type) %>% unique())
density.df$type <- factor(density.df$type)
feature.distribution.plot <- suppressWarnings(plotly::plot_ly(x=density.df$x,y=density.df$y,type='scatter',mode='lines',color=density.df$type) %>%
plotly::layout(title=plot.title,xaxis=list(title="Value",zeroline=F),yaxis=list(title="Density",zeroline=F)) %>%
plotly::add_annotations(text="type",xref="paper",yref="paper",x=1.02,xanchor="left",y=1.02,yanchor="top",legendtitle=T,showarrow=F))
} else {
validate(
need(FALSE,"You could have a violin plot here")
)
}
}
feature.distribution.plot
} else {
NULL
}
})
1 Like

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.