rggplot2shiny

How can I use conditions to add data to a ggplot making it interactive?


I am working on an interactive plot using R shiny. The aim is to compare air quality data for different cities. This should be done in a ggplot where the user can select a pollutant (y-axis) and a possible correlation factor (e.g. air temperature, x-axis). The user should then be able to select all the cities (as CheckboxGroupInput) of which the data should be plotted. Selecting the two variables (x-/y-axis) works out fine, however I struggle to plot several cities at once.

I already created the inputs, that seem to work out fine. I can also plot one city at a time. I also managed to plot several selected cities, however they are not plotted in the same ggplot, but only the topmost plot is visible (see simplified code below).

UI:

library(shiny)
library(ggplot2)

berlin_d <- read.csv("berlin_d.csv")
london_d <- read.csv("London_d.csv")
warsaw_d <- read.csv("Warsaw_d.csv")


checkboxGroupInput(
          inputId = "city",
          label = "select a city/multiple cities",
          choices = c(
            "Berlin" = "Berlin",
            "London" = "London",
            "Warsaw" = "Warsaw"
          )
        ),

      selectInput(
        inputId = "box1",
        label = "select a variable to plot (x-axis)",
        choices = c("temperature" = "temp", 
          "month" = "month",
          "weekday" = "weekday"
        ),
        selected = "temp"
      ),
      
    
    selectInput(
      inputId = "box2",
      label = "select a pollutant to plot (y-axis)",
      choices = c("Ozone" = "O3",
                  "NO2" = "NO2",
                  "PM10" = "PM10"
      ),
    )

Server:

output$plot <- renderPlot(ggplot()+
geom_point(if (input$city=="Berlin") {aes(berlin_d[[input$box1]], berlin_d[[input$box2]])})+
geom_point(if (input$city=="London") {aes(london_d[[input$box1]], london_d[[input$box2]])})+
geom_point(if (input$city=="Warsaw") {aes(warsaw_d[[input$box1]], warsaw_d[[input$box2]])})
)

I don't understand why the data isn't displayed in the same plot. Is there a way to plot the data in one ggplot and still have the options to select the cities?


Solution

  • To answer your question a small change in your code should be enough to create the functionality you are looking for.

    You have to look at the output of input$city. If you check more than one box the vector length changes and then only the first element will be used when checking the if-clause. To avoid this, you can rewrite the if-clause as follows

    if ("Berlin" %in% input$city)
    

    The whole plot would look like this.

    ggplot() +
        geom_point(if ("Berlin" %in% input$city) {aes(berlin_d[[input$box1]], berlin_d[[input$box2]])}) +
        geom_point(if ("London" %in% input$city) {aes(london_d[[input$box1]], london_d[[input$box2]])}) +
        geom_point(if ("Warsaw" %in% input$city) {aes(warsaw_d[[input$box1]], warsaw_d[[input$box2]])})
    

    However, a much better approach would be to create one data set containing all the data, where city is just a grouping variable. Then create a reactive Expression subsetting the data in shiny according to the input filter (input$city). Then you can create a plot with one call to ggplot and setting city as a factor variable for colour, for example.