0
votes

I am trying to create a shiny app with multiple sections, the section I am having trouble with right now displays calculated values on a ggplot graph. The user selects one Target gene from a dropdown list, and the graph displays calculated analysis values against a selection of other, Control genes. So far so simple.

I have a few default Control genesets, which I have preselected and that are always displayed, and then I have an option for the user to specify their own Control genes to perform analysis against. There is a checkbox that can be ticked if the user wants to select their own Controls. The user can also select different numbers of custom Controls, whereas the default controls each have sets of 3 Control genes.

Code for the default genesets as so:

ABC_control <- reactive( 
    Analysis_function(c("ACTB", "GAPDH", "TUBB")))

And code for the custom genesets is as so:

  CUSTOM_control1 <- reactive( if (input$custom_checkbox1) {
    Analysis_function(input$custom_controls1)
  } else { NA } )

I have an if command in the Custom genesets so that they are not calculated and displayed if the tickbox is not checked.

First problem: The plot still displays an x axis label for the Custom control even if none is selected and the checkbox is not ticked. This is not a major problem, just an annoying one. 1

The second problem:

When displaying just the default genesets everything runs perfectly. And when the user selects their own Control genes, everything runs fine. 2

The problem is when the user ticks the CheckboxInput(), and the selectizeInput() for the custom control genes is still empty, the graph goes and re-orders its x-axis into alphabetical order, rather than the levels order that I have specified earlier. As soon as a Control gene is selected, it re-orders back into the levels order. The problem only occurs when the selectizeInput box is empty, or a new gene is being selected. 3

How can I force the plot to always display in the correct levels order, even when the reactive custom input is empty? Also, preferably, how can I prevent the Custom input from being displayed on the graph at all unless the checkbox is ticked.

A full Shiny app data is below:


#### Load packages ####
library(shiny)
library(ggplot2)
library(dplyr)
#### Load data files ####
load("GeneNames.Rda")
load("Dataset.Rda")
#### Define UI  ####
ui <- fluidPage(
  #### Sidebar inputs ####
  sidebarLayout(
    sidebarPanel(width = 3,
                 #first wellpanel for selecting Target gene
                 h4("Target gene selection"),
                 wellPanel(
                   selectInput(
                     inputId = "gene_select",
                     label = NULL,
                     choices = GeneNames,
                     selected = "ESAM")),
                 #Second wellpanel for selecting custom Control genes
                 h4("Custom control genes"),
                 wellPanel(
                   checkboxInput(inputId = "custom_checkbox1",
                                 label = "Custom 1:"),
                   conditionalPanel(condition = "input.custom_checkbox1 == true",
                                    selectizeInput(inputId = "custom_controls1",
                                                   label = NULL,
                                                   choices = GeneNames,
                                                   multiple = TRUE,
                                                   options = list(openOnFocus = FALSE, closeAfterSelect = TRUE, maxOptions = 50, maxItems = 6))))
    ),
    #### Mainpanel results Normal ####
    mainPanel(width = 9,
              #HTML code to have the last entry in any tables bolded (last entry is Mean in all tables)
              #Results title and main bar plot graph
              fluidRow(plotOutput(outputId = "celltype_bar_plot"),width = 9)
    )))
#### Define server ####
server <- function(input, output) {
  target_gene <- reactive({
    input$gene_select
  })
  #### calculations  ####
  Analysis_function <- function(controls){
    cor(Dataset[, target_gene()], Dataset[, controls])
  }
  ABC_control <- reactive( 
    Analysis_function(c("ACTB", "GAPDH", "TUBB")))
  GHI_control <- reactive(
    Analysis_function(c("ACTB", "GAPDH", "TUBB")))
  DEF_control <- reactive(
    Analysis_function(c("ACTB", "GAPDH", "TUBB")))
  CUSTOM_control1 <- reactive( if (input$custom_checkbox1) {
    Analysis_function(input$custom_controls1)
  } else { NA } )

  #### Analysis datatables Normal ####
  control_list <- c("ABC_control", "GHI_control", "DEF_control", "CUSTOM_control1")
  analysis_list <- reactive({ list(ABC_control(), GHI_control(), DEF_control(), CUSTOM_control1()) })
  #generating melted data table of the induvidual analysed gene values, transposed to get in right format, and times = c(length()) to replicate titles the correct no of times
  values_list <- reactive({
    data.frame(Control_types2 = factor(rep(control_list, times = c(unlist(lapply(analysis_list(), length)))), levels =control_list), 
               values =  c(unlist(lapply(analysis_list(), t))))
  })
  #Generating data table of the means of analysed values above
  Mean_list <- reactive({
    data.frame(Control_types = factor(control_list, levels =control_list),
               Mean_correlation = c(unlist(lapply(analysis_list(), mean))))
  })
  #### Main Bar Plot Normal ####
  output$celltype_bar_plot <- renderPlot({
    ggplot() +
      geom_point(data = values_list(),aes(x=Control_types2, y=values,size = 7, color = Control_types2), show.legend = FALSE, position=position_jitter(h=0, w=0.1), alpha = 0.7) +
      geom_boxplot(data = Mean_list(), aes(Control_types, Mean_correlation), size = 0.5, colour = "black") 
  })
  
}
#### Run application ####

shinyApp(ui = ui, server = server)
1
Have you tried using ordered() instead of factor() to force the order to be correct? Also, have you removed CUSTOM_control1 from the control_list before setting the levels? - Adam Sampson
Just tried using ordered() instead but didn't seem to change anything. I didn't understand what you mean about removing the CUSTOM_control1 from the control_list though. I tried to just remove it and it caused errors. How would I set it so that it removes the CUSTOM_control1 only when the checkbox is unticked? - Phil D

1 Answers

1
votes

I can't fully test this solution since the data you provided isn't available (so I can't run the app), but I suspect that the following should help.

First, by using ordered or factor(..., ordered = TRUE) you can tell the graph what order to put label in.

Second, in order to prevent the column from showing up on the graph you must remove all datapoints for that column INCLUDING NA.

control_list <- c("ABC_control", "GHI_control", "DEF_control", "CUSTOM_control1")

# Some data to try out
values_list <- data.frame(
  Control_types2 = ordered(rep(control_list, times = 4), levels =control_list),
  values = c(0.25,0.50,0.75,NA)
)

Mean_list <- data.frame(
  Control_types = ordered(control_list, levels =control_list),
  Mean_correlation = c(0.25,0.50,0.75,NA)
)

# Original plot code
ggplot() +
  geom_point(data = values_list,aes(x=Control_types2, y=values,size = 7, color = Control_types2), show.legend = FALSE, position=position_jitter(h=0, w=0.1), alpha = 0.7) +
  geom_boxplot(data = Mean_list, aes(Control_types, Mean_correlation), size = 0.5, colour = "black")

enter image description here

# New plot with NA values removed
ggplot() + 
  geom_point(data = values_list %>% filter(!is.na(values)),
             aes(x=Control_types2, y=values,size = 7, color = Control_types2), 
             show.legend = FALSE, 
             position=position_jitter(h=0, w=0.1), 
             alpha = 0.7) +
  geom_boxplot(data = Mean_list %>% filter(!is.na(Mean_correlation)), 
               aes(Control_types, Mean_correlation), 
               size = 0.5, 
               colour = "black")

enter image description here