1
votes

I have created a simplified Shiny dashboard. Data in the dashboard are based on dataset foo containing 3 variables "selVar1", "selVar2" and "val".

The sidebar panel consists of two parts. An input control for selecting either the selVar1 or selVar2 column and a conditional panel showing the unique values of either selVar1 or selVar2 (conditional values based on selectInput's selVar).

  • If selVar == selVar1 is selected, then the unique values of column foo$selVar1 are shown
  • If selVar == selVar2 is selected then the unique values of column foo$selVar2 are shown

The output is a single value after filtering dataset foo based on the value selected in the conditional filter.

Issue

I can't seem to formulate the filter-statement correctly. Dynamic referall of input$selVar doesn't work: filter(input$selVar == input$selData), while explicitely mentioning selVar1 in the filter statement does work, but loses dynamic behavior: filter(selVar1 == input$selData). I have tried multiple combinations of using filter_ or filter, but I can't seem to get it right. How can I obtain dynamic filtering of the dataset based on the result of the input-control buttons? Seems I don't really understand what is happening with the non-standard versus standard evaluation expression to make it work.

  #generate textOutput
  outp <- reactive({
    tmp <- foo %>%
      select_(input$selVar, 'val') %>%
      filter(input$selVar == input$selData) %>%
      summarise(val = sum(val)) %>%
      select(val) %>%
      as.character()
  })

Example

#Input dataset foo:
  selVar1 selVar2 val
       1       b  10
       2       d  30
       3       d  50
       4       c  70
       5       b  90

#input selection selVar == selVar1
#input selection conditional panel selVar 1 == 3
#output: val = 50

See below for the complete Shiny server and ui setup.

library(shiny)
library(shinydashboard)
library(dplyr)

#dataset
foo <- structure(list(selVar1 = 1:5, 
                          selvar2 = c("b", "d", "d", "c","b"), 
                          val = c(10, 30, 50, 70, 90)), 
                     .Names = c("selVar1", "selVar2","val"), row.names = c(NA, -5L), class = "data.frame")

#Selection lists for conditional selection input:
    lstSelVar <- c('selVar1', 'selVar2')
    lstVar1 <- unique(foo$selVar1)[order(unique(foo$selVar1))]
    lstVar2 <- unique(foo$selVar2)[order(unique(foo$selVar2))]

#UI setup: 

'== sidebar
========================'

sidebar <- dashboardSidebar(
  sidebarMenu(
    selectInput("selVar", h5("Select variable:"), choices = as.list(lstSelVar), selected = 1),
    conditionalPanel(
      condition = "input.selVar == 'selVar1'",
      selectInput("selData", h5("Select value:"), choices = as.list(lstVar1), selected = 1)
    ),
    conditionalPanel(
      condition = "input.selVar == 'selVar2'",
      selectInput("selData", h5("Select value:"), choices = as.list(lstVar2), selected = 1)
    )
  )
)



'== body
========================'

body <- dashboardBody(
    fluidRow(
      column(
          dataTableOutput("tbl"), width = 3
      ),
      column(
        box(
          h4("Single output value:"),
          textOutput("outpVal")
        ), width = 3
      )      
    )
)

'== Define UI for application
========================'

ui <- dashboardPage(
  dashboardHeader(title = "Conditional Panels"),
  sidebar,
  body
)

'== Define server logic
========================'
server <- function(input, output) {
  output$tbl <-  renderDataTable(foo)  


  #generate textOutput
  outp <- reactive({
    tmp <- foo %>%
      select_(input$selVar, 'val') %>%
      filter(input$selVar == input$selData) %>%
      summarise(val = sum(val)) %>%
      select(val) %>%
      as.character()
  })

  output$outpVal <- renderText({
    outp()
  })
}

'== Run the application
========================'
shinyApp(ui = ui, server = server)
1
When doing filter(input$selVar == input$selData), that checks nothing within the dataset. It's analogous to saying mtcars %>% filter(1 == 2). Perhaps you should read dplyr.tidyverse.org/articles/programming.html? - r2evans
You can try tmp <- foo %>% select_at(vars(input$selVar, 'val')) %>% filter_at(vars(input$selVar), all_vars(.== input$selData)) %>% summarise(val = sum(val)) %>% select(val) %>% as.character() - akrun

1 Answers

2
votes

It would be better to have different names for the selectInput. Also, we can use the select_at and filter_at for selecting and filtering rows.

sidebar <- dashboardSidebar(
  sidebarMenu(
    selectInput("selVar", h5("Select variable:"), choices = as.list(lstSelVar), selected = 1),
    conditionalPanel(
      condition = "input.selVar == 'selVar1'",
      selectInput("selData1", h5("Select value:"), choices = as.list(lstVar1), selected = 1)
    ),
    conditionalPanel(
      condition = "input.selVar == 'selVar2'",
      selectInput("selData2", h5("Select value:"), choices = as.list(lstVar2), selected = 1)
    )
  )
)






body <- dashboardBody(
  fluidRow(
    column(
      dataTableOutput("tbl"), width = 3
    ),
    column(
      box(
        h4("Single output value:"),
        textOutput("outpVal")
      ), width = 3
    )      
  )
)



ui <- dashboardPage(
  dashboardHeader(title = "Conditional Panels"),
  sidebar,
  body
)


server <- function(input, output) {
  output$tbl <-  renderDataTable(foo)  





  #generate textOutput

  outp <- reactive({
   sD <- if(input$selVar == 'selVar1') input$selData1 else input$selData2

    tmp <- foo %>%
      select_at(vars(input$selVar, 'val')) %>%
      filter_at(vars(input$selVar), all_vars(.== sD)) %>%
      summarise(val = sum(val)) %>%
      select(val) %>%
      as.character()
  })


  output$outpVal <- renderText({
    outp()
  })
}


shinyApp(ui = ui, server = server)

-output

enter image description here

enter image description here