Search code examples
rshinyrendergeom-bar

How to color specific values from a variable to show them (as a bar graph and table) in Shiny?


I'm trying to create a shiny app where I can select as many countries as I want with two objectives.

a) Create a graph (as shown below) where all countries that I select, are colored.

b) Create a table where I can see the selected countries and their values.

enter image description here

I'm using this ui:

ui <- fluidPage(
  
   sidebarLayout(
     sidebarPanel(selectInput("countryInput", "Country", choices=WorldIndicators$code, multiple = TRUE)),
     mainPanel(
       plotOutput("coolplot"), 
       br(), br(),br(),br(),br(),br(),br(),br(),br(),
       tableOutput("data")
     )
   )
)

And the following server:

server <- function(input, output) {
  
  
  #Graph 
  output$coolplot <- renderPlot({
    
    if (length(input$countryInput) == 0) {
      
    }
    else if (length(input$countryInput) > 0){
    ggplot(WorldIndicators, 
           aes(x = code, y = var_mean,fill=factor(ifelse(code==input$countryInput,"Selection","Rest")))) +
      geom_bar(stat="identity",width=1)+
      geom_hline(yintercept = 0,
                 color = "#C0C0C0",
                 lwd = 1)+
      scale_fill_manual(name = "Legend", values=c("#C0C0C0","#FF6700"))+
      #labs(title= "Poverty $1.9", x="Country",y="% Poverty rate")+
      theme(plot.title = element_text(hjust = 0.5, size = 24),
            legend.position="bottom",
            axis.text.x = element_text(angle = 90,hjust=0.95,vjust=0.5),
            axis.text.y = element_text(angle = 0,size=12))+
      scale_shape_manual(values = 0:200)
    }
  })
  
  #Table 
  output$data <- renderTable({
    if (length(input$countryInput) == 0) {
      return(WorldIndicators)
    }
    else if (length(input$countryInput) > 0){
      return(WorldIndicators %>% dplyr::filter(code==input$countryInput))
    }
  }, rownames = TRUE)

}

shinyApp(ui = ui, server = server)

Everything works well when I select up to 2 countries. However, once I select more than 2 countries, I can't see any color. And the table shows just the last country I selected.

Any help is really appreciated!!!

A sample from my database is as follows:

> head(WorldIndicators)
  code   var_mean
1  AGO         NA
2  ALB  2.4689646
3  ARG -1.4609972
4  ARM  1.2627773
5  AUS  4.2980800
6  AUT  0.1403338

Solution

  • When filtering (using filter() from dplyr) make sure you replace code==input$countryInput) with code %in% input$countryInput)

    I replaced it in your posted code.

    server <- function(input, output) {
      
      
      #Graph 
      output$coolplot <- renderPlot({
        
        if (length(input$countryInput) == 0) {
          
        }
        else if (length(input$countryInput) > 0){
          ggplot(WorldIndicators, 
                 aes(x = code, y = var_mean,fill=factor(ifelse(code==input$countryInput,"Selection","Rest")))) +
            geom_bar(stat="identity",width=1)+
            geom_hline(yintercept = 0,
                       color = "#C0C0C0",
                       lwd = 1)+
            scale_fill_manual(name = "Legend", values=c("#C0C0C0","#FF6700"))+
            #labs(title= "Poverty $1.9", x="Country",y="% Poverty rate")+
            theme(plot.title = element_text(hjust = 0.5, size = 24),
                  legend.position="bottom",
                  axis.text.x = element_text(angle = 90,hjust=0.95,vjust=0.5),
                  axis.text.y = element_text(angle = 0,size=12))+
            scale_shape_manual(values = 0:200)
        }
      })
      
      #Table 
      output$data <- renderTable({
        if (length(input$countryInput) == 0) {
          return(WorldIndicators)
        }
        else if (length(input$countryInput) > 0){
          return(WorldIndicators %>% dplyr::filter(code %in% input$countryInput)))
        }
      }, rownames = TRUE)
      
    }
    
    shinyApp(ui = ui, server = server)