plot world map with areas coloured according to categorization based on latitude in R

52 views Asked by At

I would like to colour geographical areas according to the values of a specific column ("Value), where the geographical areas are not Countries nor Continent, but areas defined by latitude ("North Temperate Zone", "Torrid Zone", "South Temperate Zone").

An example dataset:

df_ex <- data.frame(Area = c("North Temperate Zone", "Torrid Zone", "South Temperate Zone"), Value = c(2.8, 1.0, 4.3))

I tried with joinCountryData2Map and mapCountryData but the only categorization available seems to be the Country.

Any ideas?

1

There are 1 answers

5
Allan Cameron On

You could do this by getting the centroid of each country and assigning the latitude to a zone using cut. There are some problems with this of course; many countries span different zones, and some countries include overseas dependencies in completely different zones.

These issues aside, the basic approach would be something like this:

library(rnaturalearth)
library(sf)
library(tidyverse)

world_map <- ne_countries(returnclass = 'sf')

world_map %>%
  rowwise() %>%
  mutate(lat = tryCatch(st_centroid(geometry) %>%
                               st_coordinates() %>% getElement(2), 
                             error = \(e) {
                               st_coordinates(geometry) %>%
                                 as.data.frame() %>%
                                 getElement(2) %>%
                                 mean()}),
         lat = cut(lat, breaks = c(-91, -66.5, -23.5, 23.5, 66.5, 91), 
                   labels = c('South Frigid', 'South Temperate', 
                              'Torrid', 'North Temperate', 'North Frigid'))) %>%
  ggplot() +
  geom_sf(aes(fill = lat)) +
  geom_hline(yintercept = c(-66.5, -23.5, 0, 23.5, 66.5), linewidth = 0.1,
             color = 'gray20') +
  scale_fill_manual(NULL, values = c('#D8D8FF', '#D8FFD8', '#90B860',
                                     '#A8FFD8', '#A8D8FF')) +
  theme_void() +
  theme(legend.position = 'bottom')

enter image description here