Search code examples
rshinyplotlyreactiveselectinput

R Shiny selectInput reactivity with multiple variable output


I'm seeking assistance with my shiny dashboard issue. Essentially, I have a single selectInput menu, however want to be able to select multiple variables and have them all plotted on the same graph.

At the moment I can get it to plot a single selected variable on the plot.ly graph, however even when I select multiple variables, it will still only plot the first variable selected:

current single variable output enter image description here

Additionally, when the app is first run, I get this error until I manually select a variable:

error received when first displayed enter image description here

This is a simplified version of the code I'm working with so far:

global_indices <- read_excel("Market_Data.xlsx", 
                             sheet = 4,
                             col_names = FALSE, 
                             skip = 5)
global_indices_clean <- global_indicies[,c(1,3,7,9,13,21,23)]
colnames(global_indices_clean) <- c("Date", "Australia", "US", "UK", "Germany", "Japan", "Hong_Kong")
global_indices_2y2 <- global_indices_clean %>% filter(between(Date, now() - years(2), now()))


header <- dashboardHeader(
  title = "Dashboard"
)

sidebar <- dashboardSidebar(
  sidebarMenu(
    menuItem("Global Indices",
             tabName = "global_indices")
  )
)

body <- dashboardBody(
  tabItems(
    tabItem(tabName = "global_indices",
            fluidRow(
              box(plotlyOutput("plot_3"), title = "Developed indices", status = "primary", width = 4, ""),
              box(plotlyOutput(""), title = "", status = "primary", width = 4, ""),
              box(plotlyOutput(""), title = "", status = "primary", width = 4, "")
            ),
            fluidRow(
              box(selectInput("global_indices_input", "Indices", 
                              choices = 
                                list("Australia" = "Australia", 
                                     "US" = "US",
                                     "UK" = "UK", 
                                     "Germany" = "Germany",
                                     "Japan" = "Japan",
                                     "Hong Kong" = "Hong_Kong"),
                              multiple = TRUE), 
                  width = 4)
            )
    )
  )  
)


ui <- dashboardPage(
  header,
  sidebar,
  body
)


server <- function(input, output) {


  output$plot_3 <- renderPlotly({
    plot_3 <- plot_ly(
      global_indices_2y2, x = global_indices_2y2$Date, y = ~get(input$global_indices_input), type="scatter", mode="lines"
    )
  })

}

shinyApp(ui, server)

I can't provide the dataset itself, however below is a small section of it:

> str(global_indices_2y2)
'data.frame':   478 obs. of  7 variables:
 $ Date     : POSIXct, format: "2018-01-29" "2018-01-30" "2018-01-31" "2018-02-01" ...
 $ Australia: num  107 106 106 107 108 ...
 $ US       : num  113 112 112 112 110 ...
 $ UK       : num  104 103 102 102 101 ...
 $ Germany  : num  103.9 102.9 102.8 101.4 99.7 ...
 $ Japan    : num  116 114 113 115 114 ...
 $ Hong_Kong: num  120 118 119 118 118 ...

I've read through dozens of threads on here over the last few days, however they all seem to focus on issues around multiple selectInput parameters, instead of a single selectInput requiring the ability to select and display multiple outputs.

Any help that you are able to provide would be greatly appreciated!


Solution

  • One approach would be to create a separate reactive to filter your data, and use the filtered data in your plot. First, I would consider converting your data to long format (e.g., using tidyverse pivot_longer). For example:

    global_indices_2y2 <- data.frame(
      Date = as.POSIXct(c("2018-01-29", "2018-01-30", "2018-01-31", "2018-02-01")),
      Australia = c(107, 106, 106, 107),
      US = c(113,112,112,112),
      UK = c(104,103,102,102)
    ) %>%
      pivot_longer(cols = -Date, names_to = "country", values_to = "index")
    

    Then add reactive to filter based on multiple selections in your server:

    mydata <- reactive({
      global_indices_2y2 %>%
        filter(country %in% input$global_indices_input)
    })
    

    Then plot filtered data:

    output$plot_3 <- renderPlotly({
      plot_3 <- plot_ly(
        mydata(), 
        x = ~Date, 
        y = ~index, 
        name = ~country,
        type="scatter", 
        mode="lines"
      )
    })