1
votes

R Shiny app consists of two inputs. The values selected by the user filter data of the output plot.

The choices of the second input are dependent on the first input.

For example, company A has data for years 2019-2017 and company B has data for years 2018-2017. The user firstly chooses a company and then the second input get updated to only show years that are available for the given company.

In the example below, when user changes from company B to company A, the plot updates in two steps (which I show in the gif). The first step lasts only a fraction of second but it is visible for the user.

This is most probably because the R Shiny app firstly shows histogram for company A x 2018 pair and then updates year and shows company A x 2019.

Is there a way to avoid the intermediate step in which R Shiny shows company A x 2018 data?

This could be resolved with an action button but it requires an additional effort from the user.

Example:

library(shiny)
library(tidyverse)

# Dummy data - company A has year 2019-2017, company B has 2018-2017
company.a <- data.frame(
    company = "A",
    year = rdunif(10000, 2019, 2017),
    value = rnorm(10000)
)
company.b <- data.frame(
    company = "B",
    year = rdunif(1000, 2018, 2017),
    value = rnorm(1000)
)
data <- rbind(company.a, company.b)

# Year choices when the app starts
year.choices <- data %>% 
    filter(company == unique(data$company)[1]) %>% 
    select(year) %>% 
    arrange(desc(year)) %>% 
    unique() %>% 
    pull()

ui <- fluidPage(
    sidebarLayout(
        sidebarPanel(
            selectInput("company", "Choose company:", choices = unique(data$company)),
            selectInput("year", "Choose year:", choices = year.choices)
        ),
        mainPanel(plotOutput("distPlot"))
    )
)

server <- function(input, output, session) {
    # The list of years gets updated when the user changes company
    observeEvent(input$company, { 
        year.choices <- data %>% 
            filter(company == input$company) %>% 
            select(year) %>% 
            arrange(desc(year)) %>% 
            unique() %>% 
            pull()
        updateSelectInput(session, "year", choices = year.choices)
    })

    # Plot for the chosen company and year
    output$distPlot <- renderPlot({
        plot.data <- data %>% filter(company == input$company & year == input$year) %>% select(value) %>% pull()
        hist(plot.data)
    })
}

shinyApp(ui = ui, server = server)

Gif: Gif showing that R Shiny updates plot in two steps

1

1 Answers

0
votes

I think you can simply isolate input$company in the renderPlot:

output$distPlot <- renderPlot({
    plot.data <- data %>% filter(company == isolate(input$company) & year == input$year) %>% select(value) %>% pull()
    hist(plot.data)
})

Indeed, although input$company is isolated, the renderPlot will still be reactive to a change of input$company, because such change triggers a change of input$year.