Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating reactive renderUI

Tags:

r

shiny

I am following this tutorial to learn to build Shiny apps. In the final version, the renderUI() for "Country" just takes all of the countries in the dataset. Is there a way to make this list reactive/filtered based on the price range selected with the slider?

Here is the relevant code:

output$countryOutput <- renderUI({
    selectInput("countryInput", "Country",
                sort(unique(bcl$Country)),
                selected="CANADA")
  })

And here is the entire. very simple app:

library(shiny)
library(ggplot2)
library(dplyr)

bcl <- read.csv("bcl-data.csv", stringsAsFactors = FALSE)

ui <- fluidPage(
         titlePanel("BC Liquor Prices", windowTitle = "Mmmmm yeh"),
         sidebarLayout(
           sidebarPanel(
             sliderInput("priceInput", "Price",
                         min = 0, max = 100,
                         value = c(25, 40), pre = "$"
                         ),
             radioButtons("typeInput", "Product type",
                          choices = c("BEER", "REFRESHMENT", "SPIRITS", "WINE"),
                          selected = "WINE"
                          ),
             uiOutput("countryOutput")
           ),
           mainPanel(plotOutput("coolplot"),
                     br(),
                     br(),
                     tableOutput("results")
                     )
           )
      )
server <- function(input, output, session) {

  filtered <- reactive({
    if (is.null(input$countryInput)) {return(NULL)} 

    bcl %>%
      filter(
        Price >= input$priceInput[1],
        Price <= input$priceInput[2],
        Type == input$typeInput,
        Country == input$countryInput
      )
  })

  output$countryOutput <- renderUI({
    selectInput("countryInput", "Country",
                sort(unique(bcl$Country)),
                selected="CANADA")
  })

  output$coolplot <- renderPlot({
    if (is.null(filtered())) {return()}
                      ggplot(filtered(), aes(Alcohol_Content)) + geom_histogram()
                    })

  output$results <- renderTable({
                      filtered()
                    })
}

shinyApp(ui = ui, server = server)
like image 820
Adam_G Avatar asked Feb 26 '26 03:02

Adam_G


1 Answers

Try this code...You need two different reactive values: 1) One to generate the country list based on first two inputs and 2) Two two generate the plot and table results based on the selected country.

Also, I changed the names to reflect the actual column names I get when reading that file. You may need to change back IF you changed them in some other part of the code.

library(shiny)
library(ggplot2)
library(dplyr)

bcl <- read.csv("bcl-data.csv", stringsAsFactors = FALSE)

ui <- fluidPage(
  titlePanel("BC Liquor Prices", windowTitle = "Mmmmm yeh"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("priceInput", "Price",
                  min = 0, max = 100,
                  value = c(25, 40), pre = "$"
      ),
      radioButtons("typeInput", "Product type",
                   choices = c("BEER", "REFRESHMENT", "SPIRITS", "WINE"),
                   selected = "BEER"
      ),
      uiOutput("countryOutput")
    ),
    mainPanel(plotOutput("coolplot"),
              br(),
              br(),
              tableOutput("results")
    )
  )
)

server <- function(input, output, session) {
  filteredForCountry <- reactive({
    bcl %>%
      filter(
        CURRENT_DISPLAY_PRICE >= input$priceInput[1],
        CURRENT_DISPLAY_PRICE <= input$priceInput[2],
        PRODUCT_SUB_CLASS_NAME == input$typeInput
      )
  })
  output$countryOutput <- renderUI({
    df <- filteredForCountry()
    if (!is.null(df)) {
      selectInput("countryInput", "Country",
                  sort(unique(df$PRODUCT_COUNTRY_ORIGIN_NAME)),
                  selected="CANADA")
    }
  })

  filteredFull <- reactive({
    if (is.null(input$countryInput)) {
      return (filteredForCountry())
    }
    bcl %>%
      filter(
        CURRENT_DISPLAY_PRICE >= input$priceInput[1],
        CURRENT_DISPLAY_PRICE <= input$priceInput[2],
        PRODUCT_SUB_CLASS_NAME == input$typeInput,
        PRODUCT_COUNTRY_ORIGIN_NAME == input$countryInput
      )
  })
  output$coolplot <- renderPlot({
    if (is.null(filteredFull())) {return()}
    ggplot(filteredFull(), aes(PRODUCT_ALCOHOL_PERCENT)) +
      geom_histogram(binwidth = 0.05)
  })

  output$results <- renderTable({
    filteredFull()
  })
}

shinyApp(ui = ui, server = server)
like image 145
Gopala Avatar answered Feb 28 '26 16:02

Gopala



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!