chas
chas

Reputation: 1645

How to subset data by user selection for plotting in R shiny app

I have a huge shiny app and met with the below issue. I tried to provide pseudo code for the problem since it is nearly impossible for my expertize to creating working app to demonstrate the problem. I hope i have conveyed with the pseudo code. Kindly help me.

Here is the pseudo code in ui.R file which has an actionButton and a radioButton with underlying selectizeInput and checkboxGroupInput input options and plotOutput to render a plot.

###ui.R#####

tabPanel("Plots",  
     fluidRow(column(4,wellPanel(
       actionButton("action_plot","Generate Plots"),  
       h6(textOutput("numheat")),
       radioButtons("plot_subset",label="Chose by sample or group?",
                    choices=c("Sample","Group"),selected="Sample"),

       conditionalPanel("input.plot_subset=='Sample'",
                        selectizeInput("view_sample_plot",
                                       label = h5("Select Samples"),
                                       choices = NULL,
                                       multiple = TRUE,
                                       options = list(placeholder = 'select samples to plot')
                        )
       ),
       conditionalPanel("input.plot_subset=='Group'",
                        checkboxGroupInput("view_group_plot",
                                           label=h5("Select Groups to View"),
                                           choices="",
                                           selected="")
       )
     )
     ),
     column(8,
            tabsetPanel(
              tabPanel(title="Plot",
                       #textOutput("which_genes"),
                       h4(textOutput("plot_title")),
                       plotOutput("plot_rna",height="800px")
     )
     )
     )
     )
     )

Below is the pseudo server.R code that observes the user input values and updates updateSelectizeInput and updateCheckboxGroupInput with choice from the default loaded R dataset. The user selected choices are used in the subsequent function to generate plot.

###server.R#####

## observed the user input and updated the selectize input and checkBoxGroup input values#####
observe({
  print("server-plot-update")
  # browser()
  data_analyzed = inputData()
  tmpgroups = data_analyzed$group_names
  tmpdatlong = data_analyzed$data_long
  tmpsamples = unique(tmpdatlong$sampleid)
  tmpynames = tmpdatlong$

  updateSelectizeInput(session,'view_sample_plot',
                       choices=tmpsamples, selected=NULL)
  updateCheckboxGroupInput(session,'view_group_plot',
                           choices=tmpgroups, selected=NULL)

})        

    #####code to render plot based on user selection value i.e. by group or samples######
    ##plot_render utilizes the R functions in Plot.R file to subset the data by user input and generate plot###

    plotdatReactive <- reactive({
     data_analyzed = inputData
     tmp <- plot_data(data_analyzed = data_analyzed,
                               yname="log2",
                               orderby="significance",
                               view_group=input$view_group_plot,
                               view_sample=input$view_sample_plot)
     tmp
    })


    output$plot_rna <- renderPlot({
      if(input$action_plot==0) return()   
    isolate({
      tmp = plotdatReactive()
      plot_render( data_analyzed=tmp,
                   yname = input$heatmapvaluename,
                   view_group=input$view_group_plot,
                   view_sample=input$view_sample_plot
                   )
    })  
 })

Pseudo Code for R functions in plot.R file

    ####plot.R#####

    ###function to subset data based on user input samples or groups###
    plot_subdat <- function(data_analyzed,
                               yname="log2",
                               orderby="significance",
                               view_sample=NULL,
                               view_group=NULL) {

      if(is.null(view_sample)) view_sample=unique(data_analyzed$sampleid)  ## sample names in the dataset
      if(is.null(view_group)) view_group=data_analyzed$group_names ## group names in the dataset


      tmpdat = data_analyzed$data_long

      ##subset dataset by **sampleid** if the user selected **samples** in SelectizeInput
      tmpdat = tmpdat%>%filter(sampleid%in%view_sample)
      subdat = filter(data_analyzed$data_long,unique_id%in%thesegenes,sampleid%in%view_sample)


      #subset dataset by **group** if the user selected **group** in checkBoxGroup input
      tmpdat = tmpdat%>%filter(group%in%view_group)
      subdat = filter(data_analyzed$data_long,unique_id%in%thesegenes,group%in%view_group)

    }


###this function generates the plot on the subset of data from the above function#####

  plot_data <- function(...)  {
  tmpdat = plot_subdat(...)
  plotdat = tmpdat$data
  plotdat
  }

The tmpdat and subdat are the inputs to generate the plot in plot_render function. If the user selects and inputs values through selectizeInput then the subsetting of data should be done by samples. If the user selects and input through checkBoxGroupInput then the subsetting should be done by group as commented in the code. I am not unable to subset the data based on user selection i.e. sample/group reactively in plot_subdat function. How can i do this reactively so that the output plot is generated as per the user selection.

Upvotes: 0

Views: 1098

Answers (1)

Ben
Ben

Reputation: 30474

I think you might want a reactive expression to subset your data.

Here is a basic working example that includes your inputs, and will plot subsetted data based on input selections reactively.

Edit:

The filtering of data is now in an external .R file, with input variables to filter on passed through.

library(shiny)

source("plot.R", local = TRUE)

ui <- fluidPage(
  mainPanel(
    tabsetPanel(
      tabPanel("Plots",  
         fluidRow(column(4,wellPanel(
           #actionButton("action_plot","Generate Plots"),  
           h6(textOutput("numheat")),
           radioButtons("plot_subset",label="Chose by sample or group?",
                        choices=c("Sample","Group"),selected="Sample"),

           conditionalPanel("input.plot_subset=='Sample'",
                            selectizeInput("view_sample_plot",
                                           label = h5("Select Samples"),
                                           choices = NULL,
                                           multiple = TRUE,
                                           options = list(placeholder = 'select samples to plot')
                            )
           ),
           conditionalPanel("input.plot_subset=='Group'",
                            checkboxGroupInput("view_group_plot",
                                               label=h5("Select Groups to View"),
                                               choices="",
                                               selected="")
           )
         )),
         column(8,
                tabsetPanel(
                  tabPanel(title="Plot",
                           #textOutput("which_genes"),
                           h4(textOutput("plot_title")),
                           plotOutput("plot_rna",height="800px")
                  )
                )
         )
        )
      )
    )
  )
)

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

  observe({
    updateSelectizeInput(session,'view_sample_plot',
                           choices=unique(mtcars$gear), selected=NULL)
    updateCheckboxGroupInput(session,'view_group_plot',
                             choices=unique(mtcars$cyl), selected=NULL)
  })    

  plot_prepare <- reactive({
    if (input$plot_subset == "Sample") {
      plot_subdat(mtcars, "gear", input$view_sample_plot)
    } else {
      plot_subdat(mtcars, "cyl", input$view_group_plot)
    } 
  })

  output$plot_rna <- renderPlot({
    plot(plot_prepare())
  })

}

shinyApp(ui, server)

plot.R

# plot.R file

library(tidyverse)

plot_subdat <- function(data, variable, choices) {
  data %>%
    filter((!!sym(variable)) %in% choices) %>%
    select(c(!!sym(variable), mpg))
}

Upvotes: 1

Related Questions