Search code examples
rshinygooglevis

Tooltip text in gvisGeoChart to display differently for NA entries


I have an app that displays countries in different colours according to their ranking. When you hover over the country, a box appears that displays their rank number, like so:

enter image description here

However, not all countries have enough data to qualify their ranking. For these countries, I want to show the name of the country and text that says "insufficient data" but that's it. You can see below that I haven't quite managed this because it still shows "Rank:" underneath. I'm sure that I've constructed the tooltip wrongly but I can't figure out how to fix it. How can I remove the "Rank:" for countries that don't have a rank? Or alternatively, how do I move "Insufficient data" to after "Rank:" for countries that don't have a rank?

enter image description here

Here is the code:

library(shiny)
library(googleVis)
library(dplyr)
library(DT)

# Load your data
combined_vul_data <- 
  structure(list(ISO3 = c("AF", "AL", "DZ", "AD", "AO", "AG", "AR", 
                          "AM", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", 
                          "BJ", "BT"), Name = c("Afghanistan", "Albania", "Algeria", "Andorra", 
                                                "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", 
                                                "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", 
                                                "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan"
                          ), vul_capacity_Rank_2021 = c(0.709035449, 0.511126182, 0.523332101, 
                                                        NA, 0.740026186, 0.621133795, 0.446088596, 0.462491218, 0.296565054, 
                                                        0.26689445, 0.47917568, NA, 0.453936004, 0.649876424, 0.398904506, 
                                                        0.386808093, 0.27763708, 0.547525366, 0.763503499, 0.635633065
                          )), class = "data.frame", row.names = c(NA, -20L))


# Define UI for the map
ui <- fluidPage(
  titlePanel(div(span("Country Rankings"), style={'padding-top: 15px'})),
  tabsetPanel(
    tabPanel("Vulnerability Map",
             sidebarLayout(
               sidebarPanel(
                 selectInput("year", "Select Year", choices = 2021, selected = 2021),
                 selectInput("category", "Select Category", 
                             choices = list("Adaptive Capacity" = "vul_capacity"), selected = "vul_vulnerability")
               ),
               mainPanel(
                 htmlOutput("map")
               )
             )
    )
  )
)

# Define server logic for the map
server <- function(input, output) {
  output$map <- renderGvis({
    year <- input$year
    category <- input$category
    
    # Create the column name for the selected year and category
    rank_column <- paste(category, "_Rank_", year, sep = "")
    
    # Filter and prepare the data
    map_data <- combined_vul_data %>%
      select(ISO3, Name, Rank = !!sym(rank_column)) %>%
      mutate(Tooltip = ifelse(is.na(Rank), paste(Name, "- Insufficient data"), paste(Name)))
    
    # Update locationvar column
    map_data <- map_data %>%
      mutate(Location = ifelse(Name %in% c("Congo (Brazzaville)", "Congo (Kinshasa)"), ISO3, Name))
    
    # Determine the range of the Rank values
    min_rank <- min(map_data$Rank, na.rm = TRUE)
    max_rank <- max(map_data$Rank, na.rm = TRUE)
    
    # Create the map
    gvisGeoChart(map_data, locationvar = "Location", colorvar = "Rank",
                 hovervar = "Tooltip",  
                 options = list(colorAxis = paste0("{minValue:", min_rank, ", maxValue:", max_rank, ", colors:['#00FF00', '#FFFF00', '#FF0000']}"),
                                backgroundColor = '#81d4fa', datalessRegionColor = '#f5f5f5',
                                defaultColor = '#f5f5f5',
                                tooltip = "{isHtml: true}",
                                width = "100%",
                                height = "500px"))  
  })
  
}

shinyApp(ui = ui, server = server)

Solution

  • You need:

    • A variable Rank.tooltip which defines the body of the tooltip. Here we set this to "" if is.na(Rank) (as required) and we manually set the default info and style otherwise using HTML:

      Rank.tooltip =  ifelse(is.na(Rank), "", paste("Rank: <b>", round(Rank, 3), "</b>"))
      
    • A variable Tooltip.header which defines the header of the tooltip, here with the additional part if is.na(Rank):

      Tooltip.header = ifelse(is.na(Rank), paste(Name, "- Insufficient data"), Name)
      

      This is also the hovervar in the options.

    Then it looks like this for a country with enough data:

    enter image description here

    And like this for a country without enough data (here manually set to Australia only for testing purposes):

    enter image description here

    library(shiny)
    library(googleVis)
    library(dplyr)
    library(DT)
    
    # Load your data
    combined_vul_data <- 
      structure(list(ISO3 = c("AF", "AL", "DZ", "AD", "AO", "AG", "AR", 
                              "AM", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", 
                              "BJ", "BT"), Name = c("Afghanistan", "Albania", "Algeria", "Andorra", 
                                                    "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", 
                                                    "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", 
                                                    "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan"
                              ), vul_capacity_Rank_2021 = c(0.709035449, 0.511126182, 0.523332101, 
                                                            NA, 0.740026186, 0.621133795, 0.446088596, 0.462491218, 0.296565054, 
                                                            0.26689445, 0.47917568, NA, 0.453936004, 0.649876424, 0.398904506, 
                                                            0.386808093, 0.27763708, 0.547525366, 0.763503499, 0.635633065
                              )), class = "data.frame", row.names = c(NA, -20L))
    
    
    # Define UI for the map
    ui <- fluidPage(
      titlePanel(div(span("Country Rankings"), style={'padding-top: 15px'})),
      tabsetPanel(
        tabPanel("Vulnerability Map",
                 sidebarLayout(
                   sidebarPanel(
                     selectInput("year", "Select Year", choices = 2021, selected = 2021),
                     selectInput("category", "Select Category", 
                                 choices = list("Adaptive Capacity" = "vul_capacity"), selected = "vul_vulnerability")
                   ),
                   mainPanel(
                     htmlOutput("map")
                   )
                 )
        )
      )
    )
    
    # Define server logic for the map
    server <- function(input, output) {
      output$map <- renderGvis({
        year <- input$year
        category <- input$category
        
        # Create the column name for the selected year and category
        rank_column <- paste(category, "_Rank_", year, sep = "")
        
        # Filter and prepare the data
        map_data <- combined_vul_data %>%
          select(ISO3, Name, Rank = !!sym(rank_column)) %>%
          mutate(Rank.tooltip = ifelse(is.na(Rank), "", paste("Rank: <b>", round(Rank, 3), "</b>"))) |> 
          mutate(Tooltip.header = ifelse(is.na(Rank), paste(Name, "- Insufficient data"), Name))
        
        # Update locationvar column
        map_data <- map_data %>%
          mutate(Location = ifelse(Name %in% c("Congo (Brazzaville)", "Congo (Kinshasa)"), ISO3, Name))
        
        # Determine the range of the Rank values
        min_rank <- min(map_data$Rank, na.rm = TRUE)
        max_rank <- max(map_data$Rank, na.rm = TRUE)
        
        # Create the map
        gvisGeoChart(map_data, locationvar = "Location", colorvar = "Rank",
                     hovervar = "Tooltip.header",  
                     options = list(colorAxis = paste0("{minValue:", min_rank, ", maxValue:", max_rank, ", colors:['#00FF00', '#FFFF00', '#FF0000']}"),
                                    backgroundColor = '#81d4fa', datalessRegionColor = '#f5f5f5',
                                    defaultColor = '#f5f5f5',
                                    tooltip = "{isHtml: true}",
                                    width = "100%",
                                    height = "500px"))  
      })
      
    }
    
    shinyApp(ui = ui, server = server)