14 Map Plots with Highcharts

Hugo Ginoux

Highcharts is originally an extremely complete Javascript library for data visualization. Its R wrapper version is the library “highcharter”. It is more difficult to understand than ggplot2 but provides an interactivity that is very satisfying.

In this chapter, we will explore the possibility to create map charts, that is to say heatmaps where the colored cells have the shape of countries, regions or states. Here is a raw example, showing the GDP of each state in the US (with random data):

mapdata <- get_data_from_map(download_map_data("custom/usa-and-canada"))

fake_gdp <- data.frame(code=mapdata$`hc-a2`) %>%
  mutate(value = 1e5 * abs(rt(nrow(mapdata), df = 10)))

hcmap(
  "custom/usa-and-canada",
  data = fake_gdp,
  value = "value",
  joinBy = c("hc-a2", "code"),
  dataLabels = list(enabled = TRUE, format = "{point.name}"),
  borderColor = "#FAFAFA",
  borderWidth = 0.1,
  tooltip = list(
    valueDecimals = 2,
    valuePrefix = "$",
    valueSuffix = "USD"
  )
) %>%
  hc_title(text = "Fake GDP per State") %>%
  hc_add_theme(hc_theme_ffx())

Spectacular, isn’t it ? Let’s dive into the different parts of the code with another example plotting the proportion of Christians in 2020 in the different European countries.

14.0.1 Collect data

You need to have a dataframe containing at least the name of the contry and the value to plot in the heatmap. In our example, the data comes from https://www.worldreligiondatabase.org/. I downloaded it under the form of an xlsx file, and stored it into my personal server.

data = read_excel("resources/mapcharts/religions.xlsx") 
data = data[data[['Religion 1']]=='Christians', c('Country Name','Religion 1','Pct_2020')]

head(data)
## # A tibble: 6 × 3
##   `Country Name` `Religion 1` Pct_2020
##   <chr>          <chr>           <dbl>
## 1 Afghanistan    Christians   0.000194
## 2 Albania        Christians   0.376   
## 3 Algeria        Christians   0.00295 
## 4 American Samoa Christians   0.980   
## 5 Andorra        Christians   0.908   
## 6 Angola         Christians   0.929

14.0.2 Download the map data and filter

Then, you need to download the map info with get_data_from_map(download_map_data(name_of_geography)). The list of available geographies with examples is here : https://code.highcharts.com/mapdata/ (there are a lot!). In our example, we need a map of Europe.

mapdata = get_data_from_map(download_map_data("custom/europe"))

mapdata
## # A tibble: 50 × 14
##    hc-gr…¹ hc-mi…² hc-mi…³ hc-ke…⁴ `hc-a2` name  label…⁵ count…⁶ subre…⁷ regio…⁸
##    <chr>     <dbl>   <dbl> <chr>   <chr>   <chr> <chr>   <chr>   <chr>   <chr>  
##  1 admin0     0.19    0.44 dk      DK      Denm… 4       Den.    Northe… Europe…
##  2 admin0     0.56    0.16 fo      FO      Faro… 6       Faeroe… Northe… Europe…
##  3 admin0     0.09    0.39 hr      HR      Croa… 6       Cro.    Southe… Europe…
##  4 admin0     0.34    0.59 nl      NL      Neth… 5       Neth.   Wester… Europe…
##  5 admin0     0.6     0.53 ee      EE      Esto… 6       Est.    Northe… Europe…
##  6 admin0     0.54    0.49 bg      BG      Bulg… 4       Bulg.   Easter… Europe…
##  7 admin0     0.38    0.53 es      ES      Spain 2       Sp.     Southe… Europe…
##  8 admin0     0.44    0.38 it      IT      Italy 2       Italy   Southe… Europe…
##  9 admin0     0.68    0.41 sm      SM      San … 6       S.M.    Southe… Europe…
## 10 admin0     0.62    0.44 va      VA      Vati… 6       Vat.    Southe… Europe…
## # … with 40 more rows, 4 more variables: `iso-a3` <chr>, `iso-a2` <chr>,
## #   `woe-id` <chr>, continent <chr>, and abbreviated variable names
## #   ¹​`hc-group`, ²​`hc-middle-x`, ³​`hc-middle-y`, ⁴​`hc-key`, ⁵​labelrank,
## #   ⁶​`country-abbrev`, ⁷​subregion, ⁸​`region-wb`

Then, we only keep the rows where the country is in Europe : we filter data by mapdata.

data = data[data[['Country Name']]%in%mapdata$name,]

14.0.3 Plot the map

We are now ready to plot a first version of the map! We simply have to call the function hcmap with these arguments:

  • which map we will use : in our case, “custom/europe” (the same argument than inside download_map_data())
  • data : the dataframe containing the names of the countries and the value to plot
  • value : the name of the column used in the heatmap : in our case, “Pct_2020”
  • joinBy : the names of the columns in the 2 dataframes corresponding to the names of the countries. The names must correspond : “UK” in the first one and “United Kingdom” in the other would not work
hcmap(
  "custom/europe",
  data = data,
  value = "Pct_2020",
  joinBy = c("name", "Country Name")
)

The result is already interesting. But some parameters can be added to make the chart even more impressive.

14.0.4 Parameters

14.0.4.1 Add labels

The parameter “datalabels” can display the names of the countries.

hcmap(
  "custom/europe",
  data = data,
  value = "Pct_2020",
  joinBy = c("name", "Country Name"),
  dataLabels = list(enabled = TRUE, format = "{point.name}")
)

14.0.4.2 Plot in %

The parameter “tooltip” allows us to modify what is displayed when the mouse hovers a country. Here, I plotted the proportion in %, rounded it to only 1 decimal and added a suffix “%”.

data['Pct_2020_%'] = data['Pct_2020']*100

hcmap(
  "custom/europe",
  data = data,
  value = "Pct_2020_%",
  joinBy = c("name", "Country Name"),
  dataLabels = list(enabled = TRUE, format = "{point.name}"),
  tooltip = list(
    valueDecimals = 1,
    valueSuffix = '%'
  )
)

14.0.4.3 Add title, theme, colors

You can add a title with the function “hc_title”. It is also possible to add subtitles. The function “hc_add_theme” adds a theme. Finally, you can change the min and max colors of the heatmap by giving the hexadecimal codes in the function “hc_colorAxis”. The missing values would always appear in white.

hcmap(
  "custom/europe",
  data = data,
  value = "Pct_2020_%",
  joinBy = c("name", "Country Name"),
  dataLabels = list(enabled = TRUE, format = "{point.name}"),
  tooltip = list(
    valueDecimals = 1,
    valueSuffix = '%'
  )
) %>%
  hc_title(text = "Proportion of Christian per country in 2020") %>%
  hc_add_theme(hc_theme_ffx()) %>% 
  hc_colorAxis(minColor = "#4242f5", maxColor = "#f54242")