emr2
emr2

Reputation: 1722

How can I show different plots depending on the user's input in Shiny?

I have this data frame:

> df
  genes  enst  x  y
1 Gene1 ENST1 25 14
2 Gene1 ENST2 60 25
3 Gene1 ENST3 12  5
4 Gene2 ENST1  9 34
5 Gene2 ENST2 14 12
6 Gene3 ENST1 10  1

I am trying to create a Shiny App which allows me to select genes and transcripts. If you select a gene (for example, Gene1), you will have an option to select which transcript do you want (in this case, ENST1, ENST2, ENST3). image 1

The thing is that I want to draw 2 plots. If you click "gene" (level:gene) it will sum all the values from that gene. For example, for the first gene, which has 3 transcripts, the total value of x will be 20+60+12=92 and the total value of y will be 14+25+5=44). So the values for plotting gene 1 will be: x=92 and y=44.

Image 2

Moreover, I would like to plot EACH transcript. For example, if you select "Gene1" and "Transcript 1", the plot will use x=25 and y=14. However, If the user decides to choose two transcripts, the user will see 2 plots. Or if the user chooses 3 transcripts, the user will see the 3 different plots.

image 3

Right now, with my code: If you select the gene, you will get the plot for the gene. image 4

However, it will show all the transcripts in the same plot. And I only want to show one transcript (or more, if the user wants) image 5

I don't know how to continue.

On the other hand, there are two things that I don't know how to implement.

Could anyone help me? Thanks in advance

My code:

library(shiny)

################ DATA #############################
genes<- c("Gene1", "Gene1", "Gene1", "Gene2", "Gene2", "Gene3")
enst <- c("ENST1", "ENST2", "ENST3", "ENST1", "ENST2", "ENST1")
x <- c(25, 60, 12, 9, 14, 10)
y <- c(14, 25, 5, 34, 12, 1)
df<- data.frame(genes, enst, x, y)

###################################################

ui <- fluidPage(
  
  # Application title
  titlePanel("Barplot"),
  
  sidebarLayout(
    sidebarPanel(
      uiOutput("selected_gene"),
      uiOutput("selected_transcript"),
      radioButtons("level", "Level:",
                   c("Gene" = "Gene",
                     "Transcript" = "Transcript")),
      h5(strong("If you want to see the plot, you have to click the button")),
      actionButton("add_plot", "See the plot"),
    ),
    
    mainPanel(
      plotOutput("plot"),
      plotOutput("plot2"),
  
      tableOutput("table1"),
      tableOutput("table2")
    )
  )
)


server <- function(session, input, output) {
  
  
  # This function gives us the list of genes.
  genes_list <- reactive({
    df$genes
    })
  
  transcripts_list <- reactive({
    
    transcripts <- subset(df, df$genes==input$gene)
    transcripts <- transcripts[,2]
    return(transcripts)
  })
  
  # This function give us a select list input, in order to be able to select the gene that we want to see
  output$selected_gene <- renderUI({
    selectizeInput(inputId = "gene", "Select one gene", choices=genes_list(), options=list(maxOptions = length(genes_list())))
  })
  
  output$selected_transcript <- renderUI({
    selectizeInput(inputId = "transcript", "Select one transcript", choices=transcripts_list(), options=list(maxOptions = length(transcripts_list())), multiple=T)
  })
  
  
  gene_values <- reactive({
    
    values <- subset(df, df[1]==input$gene)
    values$enst <- NULL
    
    if(nrow(values)>1){ #for those genes who have more than 1 transcript
      values_new <- values[2:length(values)] 
      values_new <- as.data.frame(t(colSums(values_new))) # sum the columns, transpose and transform into a dataframe
      
      gene <- values[1,] #we take the first row, only one gene but all the info.
      
      values <- cbind(values_new, gene[1]) # we bind both dataframes, however, we only want the gene name
      values <- values[,c("genes",setdiff(names(values),"genes"))] # we move the last column at the beginning
    }
    return(values)
    
  })
    
  transc_values <- reactive({

    values <- subset(df, df[1]==input$gene)
    values$genes <- NULL
  
    return(values)
  })
  
  plot_genes <- reactive({
    gene_values <- gene_values()
    barplot(c(gene_values$x, gene_values$y))
    
  })
  
  plot_transc <- reactive({
    transc_values <- transc_values()
    barplot(c(transc_values$x, transc_values$y))
    
  })
  
  
  v <- reactiveValues(plot = NULL)
  
  observeEvent(input$add_plot, {
    if(input$level == "Gene"){
      v$plot <- plot_genes()
    }
    if(input$level == "Transcript"){
      v$plot <- plot_transc()
    }
  })
  
  # This function will draw the plot
  # output$plot <- renderPlot({
  #   if (is.null(v$plot)){
  #     return()
  #   }
  #   v$plot
  # })
  
  

  output$table1 <- renderTable(gene_values())
  output$table2 <- renderTable(transc_values())
  
  output$plot <- renderPlot(plot_genes())
  output$plot2 <- renderPlot(plot_transc())
  
  
}

shinyApp(ui, server)

Upvotes: 2

Views: 2165

Answers (1)

YBS
YBS

Reputation: 21287

Perhaps you can start with this and modify according to your needs.

library(shiny)
library(ggplot2)
library(DT)
################ DATA #############################
genes<- c("Gene1", "Gene1", "Gene1", "Gene2", "Gene2", "Gene3")
enst <- c("ENST1", "ENST2", "ENST3", "ENST1", "ENST2", "ENST1")
x <- c(25, 60, 12, 9, 14, 10)
y <- c(14, 25, 5, 34, 12, 1)
df<- data.frame(genes, enst, x, y)

###################################################

ui <- fluidPage(
  
  # Application title
  titlePanel("Histogram"),
  
  sidebarLayout(
    sidebarPanel(
      uiOutput("selected_gene"),
      uiOutput("selected_transcript"),
      radioButtons("level", "Level:",
                   c("Gene" = "Gene",
                     "Transcript" = "Transcript")),
      h5(strong("If you want to see the plot, you have to click the button")),
      div(actionButton("add_plot", "See the plot"), 
          actionButton("table", "See the table"),
          actionButton("clear", "Clear All")
          )
    ),
    
    mainPanel(
      plotOutput("plot"),
      DTOutput("table")
    )
  )
)


server <- function(input, output, session) {
  
  
  ## This function gives us the list of genes.
  genes_list <- reactive({
    unique(df$genes)
  })
  
  transcripts_list <- reactive({
    req(input$gene)
    transcripts <- subset(df, df$genes==input$gene)
    transcripts <- transcripts[,2]
    return(unique(transcripts))
  })
  
  # This function give us a select list input, in order to be able to select the gene that we want to see
  output$selected_gene <- renderUI({
    selectizeInput(inputId = "gene", "Select one gene", choices=genes_list(), options=list(maxOptions = length(genes_list())))
  })
  
  output$selected_transcript <- renderUI({
    selectizeInput(inputId = "transcript", "Select one transcript", choices=transcripts_list(), options=list(maxOptions = length(transcripts_list())), multiple=F)
  })
  
  
  gene_values <- reactive({
    req(input$gene)
    values <- subset(df, df[1]==input$gene)
    values$enst <- NULL
    
    if(nrow(values)>1){ #for those genes who have more than 1 transcript
      values_new <- values[2:length(values)] 
      values_new <- as.data.frame(t(colSums(values_new))) # sum the columns, transpose and transform into a dataframe
      
      gene <- values[1,] #we take the first row, only one gene but all the info.
      
      values <- cbind(values_new, gene[1]) # we bind both dataframes, however, we only want the gene name
      values <- values[,c("genes",setdiff(names(values),"genes"))] # we move the last column at the beginning
    }
    return(values)
    
  })
  
  transc_values <- reactive({
    req(input$transcript)
    values <- subset(df, df[2]==input$transcript)
    values$genes <- NULL
    
    return(values)
  })
  
  mydata <- reactive({
    req(input$level)
    if(input$level == "Gene"){
      df <- req(gene_values())
    }else if(input$level == "Transcript"){
      df <- req(transc_values())
    }else df <- NULL
    df
  })
  
  # plot_genes <- reactive({
  #   gene_values <- req(gene_values())
  #   barplot(c(gene_values$x, gene_values$y))
  #   
  # })
  # 
  # plot_transc <- reactive({
  #   transc_values <- req(transc_values())
  #   barplot(c(transc_values$x, transc_values$y))
  #   
  # })
  
  
  v <- reactiveValues(plot = NULL, table=NULL)
  
  observeEvent(input$add_plot, {
    v$plot <- ggplot(mydata(), aes(x=x,y=y)) + geom_bar(stat = "identity")
    v$table <- NULL  ### display only plot
  },ignoreInit = TRUE)
  
  observeEvent(input$table, {
    v$table <- req(mydata())
    v$plot <- NULL   ### display only table
  },ignoreInit = TRUE)
  
  observeEvent(input$clear, {
    v$table <- NULL
    v$plot <- NULL
  },ignoreInit = TRUE)
  
  ##  This function will draw the plot
  output$plot <- renderPlot({ v$plot })
  output$table <- renderDT({ v$table })
  
}

shinyApp(ui, server)

Upvotes: 2

Related Questions