ConorM
ConorM

Reputation: 33

Shiny: SelectInput subset based on input

Edit: Thanks for the help, there were multiple issues with my code but the main issue was that I was missing an Observe statement, the following solved the problem:

 get_ddf <- reactive({
      filter(poskick, Name == input$player)
    })

  observe({
    updateSelectInput(session, 'fixture', choices   =levels(droplevels(get_ddf()$Event)) )
  })

I want my Shiny app to have two selectInput dropdowns, the first one selecting a name and the second selcting from the events a person took part in, based on a subset created by the first input. sample data:

 PLID   Name        x_coord y_coord x_coord_end y_coord_end action  Event
 7046   Sample Name1    35    37      34          25          4    23/07/11
 7046   Sample Name1    21    11       0           0          4    23/07/11
 7046   Sample Name1    49    60      56           8          4    23/07/11
 7046   Sample Name1    46    56      72          34          4    23/07/11
 7046   Sample Name1    58    49      24          58          4    23/07/11
 7046   Sample Name1    87    57      42          52          4    23/07/11
 7046   Sample Name1    14    58      18          37          4    23/07/11
 7140   Sample Name2    38    14      11          11          4    23/07/11
 7140   Sample Name2    11    11      11          11          4    23/07/11
 7140   Sample Name2    56    8       56           8          4    23/07/11

my code UI:

library(shiny)
library(ggplot2)


poskick<-read.csv('poskicks.csv')


shinyUI(pageWithSidebar(

  headerPanel("position map"),

  sidebarPanel(



selectInput('player', 'Player', choices= attributes(poskick$Name)),
selectInput('fixture', 'Match', choices= attributes(firstsub()$Fixtu))

),

mainPanel(
  plotOutput('plot')
)
  ))

Server Code:

library(shiny)
library(ggplot2)

poskick<-read.csv('poskicks.csv')



shinyServer(function(input, output) {


  firstsub <- reactive({
     subset(poskick, poskick$Name %in% input$player)
     })

  secondsub <- reactive({
     subset(poskick, poskick$Fixtu %in% input$fixture & poskick$Name %in%    input$player )
    })


  output$plot <- renderPlot({
    p <- ggplot(data = secondsub()) + geom_segment(aes(x = x_coord, y =   y_coord, xend = x_coord_end, yend = y_coord_end))
    print(p)    }, height=700)

})

Any suggestions are appreciated, Thank You.

Upvotes: 2

Views: 4334

Answers (1)

Paul de Barros
Paul de Barros

Reputation: 1200

There were some issues in your code, like using Fixtu, which did not refer to anything. Also, I think that levels() is probably a better choice than attributes() for getting the unique values in a factor variable.

I find that it's helpful to use renderUI in the server.R file when you want the input into one widget to control the input into another. You can then put in return statements to prevent the widget from even showing up before it knows what options to offer. I do this by adding a "pick one" option that causes the next widget to not even show up. It would be better if you could make the selectInput default to NULL, but that is not an option.

Here is what I did:

server.R:

library(shiny)
library(ggplot2)

poskick<-read.csv('poskicks.csv')

shinyServer(function(input, output) {

  output$Box1 = renderUI(selectInput('player', 
                                     'Player', 
                                     c(levels(poskick$Name),"pick one"),
                                     "pick one")
  )

  output$Box2 = renderUI(
    if (is.null(input$player) || input$player == "pick one"){return() 
    }else selectInput('fixture', 
                      'Match', 
                      c(levels(poskick$Event[which(poskick$Name == input$player)]),"pick one"),
                      "pick one")
    )

  subdata1 = reactive(poskick[which(poskick$Name == input$player),])
  subdata2 = reactive(subdata1()[which(subdata1()$Event == input$fixture),])

  output$plot <- renderPlot({
    if (is.null(input$player) || is.null(input$fixture)){return()
    } else if(input$player == "pick one" || input$fixture == "pick one") { return()
    } else p <- ggplot(data = subdata2()) + geom_segment(aes(x = x_coord, y =   y_coord, xend = x_coord_end, yend = y_coord_end))
    print(p)    })

})

ui.R:

library(shiny)
library(ggplot2)
shinyUI(pageWithSidebar(
  headerPanel("position map"),
  sidebarPanel(uiOutput("Box1"),uiOutput("Box2")),
  mainPanel(plotOutput('plot')
  )
))

Upvotes: 0

Related Questions