How to use shiny to select variables to plot multiple lines over time

In this example, I have 3 variables, 2 variable domains and 2 years. I want to be able to build a shiny app where I choose combinations of 2 or 3 variables and domains to draw a chart.
Depending on the variables and domain selected, a series resulting from the mean is drawn (variable m).

library(tidyverse)
theme_set(theme_minimal())

df <- tibble(d = c(1,1,2,2),
                  year = c(2015, 2016, 2015, 2016),
                  v1 = c(3,5,4,10),
                  v2 = c(7,11,13,18),
                  v3 = c(1,2,3,4))

draw_chart <- function(df, listv, d){
  df2 <- df %>%
    gather("variable", "value", 3:5)
  df3 <- df2 %>%
    filter(variable %in% listv)
  
  df4 <- df3 %>%
    group_by(d, year) %>%
    summarise(value = mean(value)) %>%
    mutate(variable = "m")
  
  df5 <- bind_rows(df3, df4) 
  
  df5 <- df5 %>%
    mutate(year = as.character(year)) %>%
    mutate(year = as.Date(year, "%Y"))
  
  df5 <- df5 %>%
    mutate(year = lubridate::year(year))
  
  df5 <- df5 %>%
    filter(d == 1)
  # format(df5$year, "%Y")
  # Visualization
  ggplot(df5, aes(x = year, y = value)) + 
    geom_line(aes(color = variable, linetype = variable)) + 
    scale_color_discrete() +
    scale_x_continuous(breaks = c(2015,2016))
}

listv <- c("v1", "v2") # this list can change
# these are several possibilities of chosing variables
# listv <- c("v2", "v3")
# listv <- c("v1", "v3")
# listv <- c("v1", "v2", "v3")
# and d can also be chosed to be 1 or 2

draw_chart(df, listv, 2)

Hi,

It's always nice when people create a great reprex, so we can quickly come up with a solution :slight_smile: Nice job!

Since you haven't started any app building in your code yet, I assume you're new to Shiny or don't know how to start, so I kept the app to the very basics.

library(shiny)
library(ggplot2)
library(tidyverse)

theme_set(theme_minimal())

ui <- fluidPage(
  #Create input for domain (single) and variable (multiple)
  selectInput("domain", "Domain", choices = ""),
  selectInput("varSelection", "Choose 2 or 3 variables", multiple = T, choices = ""),
  
  #Set plot for output
  plotOutput("myPlot")
)

server <- function(input, output, session) {
  
  #Load your data
  df <- tibble(d = c(1,1,2,2),
               year = c(2015, 2016, 2015, 2016),
               v1 = c(3,5,4,10),
               v2 = c(7,11,13,18),
               v3 = c(1,2,3,4))
  
  #Update the domain input according to the data
  updateSelectInput(session, "domain", choices = sort(unique(df$d)))
  
  #Update the variable list (assumed all but d and year are variables of interest)
  updateSelectInput(session, "varSelection", 
                    choices = colnames(df %>% select(-d, -year)))
  
  #Load the chart function
  draw_chart <- function(df, listv, d){
    df2 <- df %>%
      gather("variable", "value", 3:5)
    df3 <- df2 %>%
      filter(variable %in% listv)
    
    df4 <- df3 %>%
      group_by(d, year) %>%
      summarise(value = mean(value)) %>%
      mutate(variable = "m")
    
    df5 <- bind_rows(df3, df4) 
    
    df5 <- df5 %>%
      mutate(year = as.character(year)) %>%
      mutate(year = as.Date(year, "%Y"))
    
    df5 <- df5 %>%
      mutate(year = lubridate::year(year))
    
    df5 <- df5 %>%
      filter(d == 1)
    # format(df5$year, "%Y")
    # Visualization
    ggplot(df5, aes(x = year, y = value)) + 
      geom_line(aes(color = variable, linetype = variable)) + 
      scale_color_discrete() +
      scale_x_continuous(breaks = c(2015,2016))
  }
  
  #Render the plot
  output$myPlot = renderPlot({
    #Only render if there are 2 or 3 variables selected
    req(between(length(input$varSelection), 2, 3))
    draw_chart(df, input$varSelection, input$domain)
  })
  
}

shinyApp(ui, server)


I highly recommend you watch or read some of the great tutorials online like the Shiny website to familiarize yourself with the coding framework of the apps.
https://shiny.rstudio.com/tutorial/

Hope this helps,
PJ

1 Like

Thank you very much. I have been studying Shiny (only for 1 day :-)). That's why I edited my question with my first (bad) trial. When I posted it I saw your answer.

No worries, you can learn from this example and modify it further to your liking.

PJ

1 Like

Well I posted again the initial version to keep the logic. I think your solution will help me now.

Everything works fine except that I can't change the domain because of the following line of code:

 df5 <- df5 %>%
            filter(d == 1)

Solved with:

df5 <- df5 %>%
            filter(d == input$domain)

Hi,

Thanks for spotting that :slight_smile:
I must have forgotten to update that during the creation of the app.

Good luck
PJ

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.