1

I am trying to build an app which displays a dataframe as a datatable. I wanted to provide users with ability to subset the datatable with selectinput and daterangeinput filters on the sidebar panel.

Heres when I ran into issues,

  • it only subsets the datatable when all the inputs are selected
  • it displays an empty datatable on loading the app
  • when one of the inputs are changed back it doesnot update the datatable.

Here is my sample code for shiny app

Region <- c("USA","UK","JPN","JPN","UK","USA","USA")
Company <- c("A","B","C","A","B","C","A")
Status <- c("Completed","In Production","In Design","New","In Production","In Design","New")
date <- c("2015-05-01","2015-05-01","2015-06-04","2015-06-20","2015-07-15","2015-08-12","2015-08-12")
date <- as.Date(date,"%Y-%m-%d")

df <- data.frame(Region, Company, Status, date)

The ui file is

ui.R

shinyUI(
   fluidPage(
       titlePanel("Summary"),

sidebarLayout(
        sidebarPanel(

            selectInput("region", 
                        label = "Choose a Region",
                        choices = c("", unique(df$Region))),

            selectInput("company", 
                        label = "Choose a company",
                        choices = c("", unique(df$Company))),

            selectInput("status", 
                        label = "Choose Proj status",
                        choices = c("", unique(df$Status))),

            dateRangeInput("projdate", 
                        label = "Date of interest:",
                        start = Sys.Date() - 60, 
                        end = Sys.Date())
            ),

        mainPanel(
            dataTableOutput("table")
        )
        )
    ))

The Server file is

    server.R

shinyServer(function(input,output){

    output$table <- renderTable({
    datadf %>% as.data.frame() %>% filter(Region == input$region & Company == input$company & Status == input$status)
        })
})

When the app launches it does not display the table without any filter applied. I am not sure if I am doing everything in the output$table function to get the output I desire.

If someone could guide me as to how I can display the datatable without any user input and then the datatable updates as userinputs are changed.

I tried placing the input factors in a reactive environment but then operation not allowed without an reactive context pops up.

David Makogon
  • 69,407
  • 21
  • 141
  • 189
user6529266
  • 27
  • 1
  • 4
  • You need to change the filter to `filter(Region %in% selection)`, where `selection` is the vector of all options if nothing selected. – Xiongbing Jin Jun 29 '16 at 19:57
  • Should it be like 'selection = c(input$Region, input$Company, input$Status)' so that if one of the inputs are chosen the display with be a datatable matching those inputs? Thanks – user6529266 Jun 29 '16 at 20:29
  • No you still need multiple filters, but I mean for each of them, if nothing is selected, you need to assume that all options are selected. For example if no region is selected, `selection` should be a vector of all regions. otherwise you get an empty result. – Xiongbing Jin Jun 29 '16 at 21:05
  • So i created individual vectors for each input such as 'regionselect <- c(levels(df$Region))' and so on. I then used 'filter(Region %in% regionselect & Status %in% statusselect & Company %in% companyselect) '. It still does not show the default complete unfiltered dataframe and does not subset when one or more of the filters are chosen. Thanks. – user6529266 Jun 29 '16 at 21:26

2 Answers2

2

===Updated answer===

Here is a working solution.

library(shiny)
library(dplyr)

Region <- c("USA","UK","JPN","JPN","UK","USA","USA")
Company <- c("A","B","C","A","B","C","A")
Status <- c("Completed","In Production","In Design","New","In Production","In Design","New")
date <- c("2015-05-01","2015-05-01","2015-06-04","2015-06-20","2015-07-15","2015-08-12","2015-08-12")
date <- as.Date(date,"%Y-%m-%d")

df <- data.frame(Region, Company, Status, date)

ui <- shinyUI(
  fluidPage(
    titlePanel("Summary"),

    sidebarLayout(
      sidebarPanel(

        selectInput("region", 
                    label = "Choose a Region",
                    choices = c("", as.vector(unique(df$Region)))),

        selectInput("company", 
                    label = "Choose a company",
                    choices = c("", as.vector(unique(df$Company)))),

        selectInput("status", 
                    label = "Choose Proj status",
                    choices = c("", as.vector(unique(df$Status)))),

        dateRangeInput("projdate", 
                       label = "Date of interest:",
                       start = Sys.Date() - 60, 
                       end = Sys.Date())
      ),

      mainPanel(
        tableOutput("table")
      )
    )
  ))

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

  output$table <- renderTable({
    region_sel <- if (nchar(input$region)==0) unique(as.vector(df$Region)) else input$region
    company_sel <- if (nchar(input$company)==0) unique(as.vector(df$Company)) else input$company
    status_sel <- if (nchar(input$status)==0) unique(as.vector(df$Status)) else input$status

    filter(df, Region %in% region_sel, Company %in% company_sel, Status %in% status_sel)
  })
})

shinyApp(ui = ui, server = server)

===Previous Answer===

Not a direct answer, but here is a very similar example that may help you.

library(shiny)
library(dplyr)

ui <- shinyUI(fluidPage(

   titlePanel("Old Faithful Geyser Data"),

   sidebarLayout(
      sidebarPanel(
        selectInput("cyl", "cyl", unique(mtcars$cyl), multiple = TRUE),
        selectInput("vs", "vs", unique(mtcars$vs), multiple = TRUE),
        selectInput("am", "am", unique(mtcars$am), multiple = TRUE)
      ),

      mainPanel(
         tableOutput("table")
      )
   )
))

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

    output$table <- renderTable({
        cyl_sel <- if (is.null(input$cyl)) unique(mtcars$cyl) else as.numeric(input$cyl)
        vs_sel <- if (is.null(input$vs)) unique(mtcars$vs) else as.numeric(input$vs)
        am_sel <- if (is.null(input$am)) unique(mtcars$am) else as.numeric(input$am)
        filter(mtcars, cyl %in% cyl_sel, vs %in% vs_sel, am %in% am_sel)
    })

})

shinyApp(ui = ui, server = server)
Xiongbing Jin
  • 11,779
  • 3
  • 47
  • 41
  • This does clear things a lot, I was able to edit to show character input instead of numeric. I tried to remove multiple = T so that the table only filters one of the variable from each input but that didnt turn out okay. How can I choose one input instead of multiple in each selectInput function and sort the dataframe accordingly and How can I have the function display the entire dataframe when none is chosen? Any help deeply appreciated. Thanks a lot for guiding towards a workable solution. – user6529266 Jun 30 '16 at 18:01
  • I've posted a fully working solution, see the updated answer – Xiongbing Jin Jun 30 '16 at 20:47
  • Using the nchar function did it !!! Thanks for the input, now I can understand it more clearly !! – user6529266 Jun 30 '16 at 21:41
0

Server.R

shinyServer(function(input,output,session){


  data_update <- reactive({

    # Compose data frame
    data.frame(
      Name = c("Region", 
               "Company",
               "Status"),
      Value = as.character(c(input$region, 
                             input$company,
                             input$status)), 
      stringsAsFactors=FALSE)
  }) 

  # Show the values using an HTML table
  output$table <- renderTable({
    data_update()
  })
})

UI.R

shinyUI(
  fluidPage(
    titlePanel("Summary"),

    sidebarLayout(
      sidebarPanel(

        selectInput("region", 
                    label = "Choose a Region",
                    choices = c("", unique(df$Region)), selected= '1'),

        selectInput("company", 
                    label = "Choose a company",
                    choices = c("", unique(df$Company)), selected= '1'),

        selectInput("status", 
                    label = "Choose Proj status",
                    choices = c("", unique(df$Status)), selected= '1'),

        dateRangeInput("projdate", 
                       label = "Date of interest:",
                       start = Sys.Date() - 60, 
                       end = Sys.Date())
      ),

      mainPanel(
        tableOutput("table")
      )
    )
  ))

GLOBAL.R

library(shiny)
library(dplyr)
library(DT)

Region <- c("USA","UK","JPN","JPN","UK","USA","USA")
Company <- c("A","B","C","A","B","C","A")
Status <- c("Completed","In Production","In Design","New","In Production","In Design","New")
date <- c("2015-05-01","2015-05-01","2015-06-04","2015-06-20","2015-07-15","2015-08-12","2015-08-12")
date <- as.Date(date,"%Y-%m-%d")

df <- data.frame(Region, Company, Status, date)

I also recommend using DT package to plot your table.

Hope it helps! Cheers

DemetriusRPaula
  • 377
  • 1
  • 10
  • Thanks for the response. I was able to produce a datatable output with the DT package but the app produces a table that show the input as value instead of subsetting the dataframe. I would like the display to be a subset of the df datatable when one of the inputs are given. For instance, if Region is selected as USA, the display should be a datatable with just field's matching USA in Region and similarly if Company is chosen as C, the display should be the row with USA in region and C in company. That's the trouble I was having with. – user6529266 Jun 29 '16 at 20:27