Home > Mobile >  Selecting a variable to plot in a bar chart with Shiny
Selecting a variable to plot in a bar chart with Shiny

Time:12-30

I have the following dataset:

enter image description here

data <- structure(list(country = c("Andorra", "Austria", "Belgium", "Denmark", "Finland", "France", "Germany", "Greece"), x48 = c(811.73, 710.0385, 765.8359, 961.434, 701.9176, 716.7308, 701.6187, 468.1942), x49 = c(655.2433, 607.8058, 628.3675, 692.426, 575.4287, 587.7711, 544.2052, 370.2103), x54 = c(2801.597, 2224.757, 2320.216, 3130.023, 2582.625, 2399.011, 2621.368, 804.5603)), class = "data.frame", row.names = c(NA, -8L))

I want to plot a double bar chart that shows, for each country in the x-axis, a bar with the values of 'x54' and a bar for either 'x48' or 'x49' like so:

enter image description here

With the following code:

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

df <- read.csv("data/salario-apartamento-europa-occidental-pequeño.csv")

  ui = fluidPage(
    titlePanel("Triple Bar Chart"),
    sidebarLayout(
      sidebarPanel(
        selectInput("x1", "Type of house:", choices = names(df)[-1], selected = names(df)[1]),
      ),
      mainPanel(
        plotOutput("plot")
      )
    )
  )
  server = function(input, output) {
    output$plot <- renderPlot({
      df_long <- df %>% pivot_longer(-country)
      ggplot(data = df_long %>% 
               filter(name %in% c("x49", "x54")),  
             aes(x = country, y = value, fill = factor(name)))  
        geom_col(position = position_dodge()) 
        scale_fill_manual(values = c("#58C114", "#DA560A"))  
        theme_light()   
        theme(axis.text.x = element_text(angle = 90))  
        scale_color_manual(name = "Metric", labels = c("1 room in the center", "Average Monthly Salary"))   
        labs(fill =" Metric", x= "Country", y= "USD")
    })
  }

# run the app
shinyApp(ui, server)

I can do it as you can see, but you'll realize that, instead of filtering by 'x54' and the input variable "x1", I'm filtering by 'x49' thus, instead of being reactive, for me to compare 'x54' and 'x48', I have to change it manually in the code.

I would like to have something similar to this:

filter(name %in% c(input$x1, "x54"))

But unfortunatelly, this doesn't work and it only plots 'x54'.

Also, how would I update the labels accordingly? (Now they stay like 'x49' and 'x54' as you can see in the picture)

It should be like so:

For 'x54': Average Monthly Salary

For 'x48': 1 room in the center

And for 'x49': 1 room outside the center

Thank you very much in advance for the help!

CodePudding user response:

In the selectInput, the object used is data and not df

selectInput("x1", "Type of house:", choices = names(df)[-1], 
        selected = names(df)[1]),
      ),
...

where

df <- read.csv("data/salario-apartamento-europa-occidental-pequeño.csv")

-full code

df <- structure(list(country = c("Andorra", "Austria", "Belgium", "Denmark", "Finland", "France", "Germany", "Greece"), x48 = c(811.73, 710.0385, 765.8359, 961.434, 701.9176, 716.7308, 701.6187, 468.1942), x49 = c(655.2433, 607.8058, 628.3675, 692.426, 575.4287, 587.7711, 544.2052, 370.2103), x54 = c(2801.597, 2224.757, 2320.216, 3130.023, 2582.625, 2399.011, 2621.368, 804.5603)), class = "data.frame", row.names = c(NA, -8L))
ui = fluidPage(
  titlePanel("Triple Bar Chart"),
  sidebarLayout(
    sidebarPanel(
      selectInput("x1", "Type of house:", choices = names(df)[-1], selected = names(df)[1]),
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)
server = function(input, output) {
  output$plot <- renderPlot({
    req(input$x1)
    df_long <- df %>% pivot_longer(-country)
    
    
    ggplot(data = df_long %>% 
             filter(name %in% c(input$x1, "x54")),  
           aes(x = country, y = value, fill = factor(name)))  
      geom_col(position = position_dodge()) 
      scale_fill_manual(values = c("#58C114", "#DA560A"), 
               labels= setNames( c("1 room in the center", "Average Monthly Salary"), c("x48", "x49")))  
      theme_light()   
      theme(axis.text.x = element_text(angle = 90))  
       labs(fill =" Metric", x= "Country", y= "USD")
  })
}

# run the app
shinyApp(ui, server)

-output

enter image description here

CodePudding user response:

Your input needs to be a reactive. https://mastering-shiny.org/basic-reactivity.html

Your server would need to look more like this.

server = function(input, output) {
  
  yourinput <- reactive({
    input$x1
  })
  
  output$plot <- renderPlot({
    df_long <- df %>% pivot_longer(-country)
    ggplot(data = df_long %>% 
             filter(name %in% c(yourinput(), "x54")),  
           aes(x = country, y = value, fill = factor(name)))  
      geom_col(position = position_dodge()) 
      scale_fill_manual(values = c("#58C114", "#DA560A"))  
      theme_light()   
      theme(axis.text.x = element_text(angle = 90))  
      scale_color_manual(name = "Metric", labels = c("1 room in the center", "Average Monthly Salary"))   
      labs(fill =" Metric", x= "Country", y= "USD")
  })
}
  • Related