3
votes

I am trying to make an app in Shiny which is dynamically subsetting a data-set 3 times by users input. Let's assume that the dataset is that

Number<- c(10, 20, 30 , 40, 50 ,60, 70, 80, 90,100,110,120,130,140)
Att1 <- c('a','a','a','a','a','a','a','b','b','b','b','b','b','b')
Att2 <- c('c','c','c','d','d','d','d','e','e','e','g','g','g','g')
Index<-c('I1','I2','I3','I4', 'I5','I6','I7','I8','I9','I10', 'I11','I12','I13','I14')
df <- data.frame(Number, Att1 , Att2,Index)

What i want to do is to create a dropdown menu that gives you the choices a or b from att1 then the choice reacts with the second drop down where the choices of the att2 are displayed but subsetted for choice att1. Depending on the choice the user then the last drop down will give him the choices for which index to choose. Now after the choice of the index a dataframe have to return with only the numbers indicated by the index and this number will be used in next steps.

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(data.table)
# Define UI for application that draws a histogram
ui <- fluidPage(

  # Application title
  titlePanel("App"),

  sidebarLayout(
    sidebarPanel(
      selectInput("Att1", "Choose Att1",choices= c(as.character(unique(df$Att1))  )),
      uiOutput("c")),
    # Show a plot of the generated distribution
    mainPanel( DT::dataTableOutput("table")

    )
  )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  Number<- c(10, 20, 30 , 40, 50 ,60, 70, 80, 90,100,110,120,130,140)
  Att1 <- c('a','a','a','a','a','a','a','b','b','b','b','b','b','b')
  Att2 <- c('c','c','c','d','d','d','d','e','e','e','g','g','g','g')
  Index<-c('I1','I2','I3','I4', 'I5','I6','I7','I8','I9','I10', 'I11','I12','I13','I14')
  df <- data.frame(Number, Att1 , Att2,Index)


  selectedData <- reactive({
    Ddata<-subset(df,Att1==input$Att1)
  })

  output$c<-renderUI({selectInput("Att2", "Choose Att2",choices= c(as.character(unique(selectedData()$Att2)) ))})
  selectedData2 <- reactive({
    Vdata<-subset(selectedData(),Att2==input$c)
    Vdata<-as.data.frame(Vdata)
    Vdata
  })

  output$table <- DT::renderDataTable({
    head(selectedData2(), n = 10)
  })



}

# Run the application 
shinyApp(ui = ui, server = server)

This is where I got as far but the problem is how can I use a reactive dataset second time in a reactive expression and also the output for the first 2 attributes is null. I am trying to solve this for days, any thoughts?

2

2 Answers

3
votes

There is a specific shiny function to update the content of a SelectInput: updateSelectInput().

If used inside an observe it can be used exactly for what you are trying to do:

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

    observe({
        input$Att1

        x <- df[df$Att1 == input$Att1, 'Att2']
        xs <- as.character(unique(x))
        updateSelectInput(session, 'Att2', choices = xs)
    })

    selectedData <- reactive({
        df[df$Att2 == input$Att2, ]
    })

    output$table <- DT::renderDataTable({
        head(selectedData(), n = 10)
    })       

}

Here is the ui for completeness

ui <- fluidPage(

    # Application title
    titlePanel("App"),

    sidebarLayout(
        sidebarPanel(
            selectInput("Att1", "Choose Att1",choices = as.character(unique(df$Att1))  ),
            selectInput("Att2", "Choose Att2",choices = NULL, selected = 1)
            ),
        # Show a plot of the generated distribution
        mainPanel( DT::dataTableOutput("table")

        )
    )
)
1
votes

Just continuing with what you have... I added "NULL" as a choice to the drop-downs, and if "NULL" is selected then the full data set is retained.

Number <- c(10, 20, 30 , 40, 50 ,60, 70, 80, 90,100,110,120,130,140)
Att1 <- c('a','a','a','a','a','a','a','b','b','b','b','b','b','b')
Att2 <- c('c','c','c','d','d','d','d','e','e','e','g','g','g','g')
Index <- c('I1','I2','I3','I4', 'I5','I6','I7','I8','I9','I10', 'I11','I12','I13','I14')
df <- data.frame(Number, Att1, Att2, Index)

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(data.table)
# Define UI for application that draws a histogram
ui <- fluidPage(

  # Application title
  titlePanel("App"),

  sidebarLayout(
    sidebarPanel(
      selectInput("Att1", "Choose Att1", choices = c("NULL", as.character(unique(df$Att1))), selected = "NULL"),
      uiOutput("c"),
      uiOutput("d")),
    # Show a plot of the generated distribution
    mainPanel( DT::dataTableOutput("table")

    )
  )
)

# Define server logic required to draw a histogram
server <- function(input, output) {

  selectedData <- reactive({
    if(input$Att1 == "NULL") Ddata <- df  #Keep full data set if NULL
    else Ddata <- subset(df, Att1 == input$Att1)

    Ddata
  })

######################
  output$c <- renderUI({selectInput("Att2", "Choose Att2", choices = c("NULL", as.character(unique(selectedData()$Att2))), selected = "NULL")})

  selectedData2 <- reactive({
    if(input$Att2 == "NULL") Vdata <- selectedData()
    else Vdata <- subset(selectedData(), Att2 == input$Att2)

    Vdata
  })
######################

#=====================
  output$d <- renderUI({selectInput("Index", "Choose Index", choices = c("NULL", as.character(unique(selectedData2()$Index))), selected = "NULL")})

  selectedData3 <- reactive({
    if(input$Index == "NULL") Fdata <- selectedData2()
    else Fdata <- subset(selectedData2(), Index == input$Index)

    Fdata
  })
#=====================

  output$table <- DT::renderDataTable({
    head(selectedData3(), n = 10)
  })
}

# Run the application 
runApp(shinyApp(ui = ui, 
         server = server), launch.browser=TRUE
)