This tutorial will guide you through creating both basic and slightly advanced maps in R using the ggplot2 and sf libraries. Our example will focus on creating a map for Latin America and the Caribbean with custom features such as color gradients, annotations, and thematic mapping.
Overview
Load and filter global data for the Latin America and Caribbean region.
Create a basic map.
Merge external data (WEO) for enhanced thematic mapping.
Add color gradients, labels, and custom styling.
First, let’s load all the necessary libraries.
Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
Attaching package: 'rnaturalearthdata'
The following object is masked from 'package:rnaturalearth':
countries110
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
here() starts at C:/IMF-R-Book
Load World Map Data
To begin, we’ll use world map data from rnaturalearth and filter it to display only Latin America and the Caribbean.
# Load world map data from rnaturalearthworld <-ne_countries(scale ="medium", returnclass ="sf")# Filter for Latin America and the Caribbeanlatam_carribean <- world %>%filter(region_un =="Americas"& subregion %in%c("Central America", "Caribbean", "South America"))
We now have a spatial dataset, latam_carribean, containing only the Latin America and Caribbean countries.
Create a Basic Map
Using this data we loaded, let’s create a basic map highlighting the countries in Latin America and the Caribbean.
ggplot(data = latam_carribean) +geom_sf(fill ="lightblue", color ="black", size =0.3) +# Use a thinner border for countrieslabs(title ="Latin America and the Caribbean",caption ="Source: Natural Earth" ) +theme_void() +# A completely clean themetheme(plot.title =element_text(size =16, face ="bold", hjust =0.5), # Center-align and style titleplot.caption =element_text(size =10, hjust =0), # Align caption to the leftpanel.background =element_rect(fill ="white", color =NA) # Optional: white background )
That was easy! We quickly created a clean, simple map for Latin America and the Caribbean. Now, let’s explore how to add more customized features to it.
Add Custom Features to the Map
We will run you through how to create an advanced map with the following features:
Color gradients to represent a ratio (e.g., GDP per capita).
Country labels for easy identification.
IMF theme for enhanced visualization.
Add in WEO Population and GDP Data
To have our map display an indicator we want, we can add in WEO data and have it diplay a color gradient representing GDP per capita. We would have to follow these steps in order to complete this:
Read the .dta file.
Select the relevant indicators.
Filter for 2023.
Convert IMF numeric codes to ISO3 codes.
Join with our spatial data.
Let’s load the previously used WEO database here.
# Read your WEO .dta fileweo <-read_dta(here("databases/WEOApr2023Pub.dta"))
Now, let’s filter to ensure we are only displaying the relevant indicators that we want and ensure we are using the year 2023.
As we learned earlier in the book, WEO uses numeric ifscode that we need to convert to iso3 codes to merge into our current dataset. Let’s do that now.
Finally, let’s merge the WEO data into the Latam_Carribean data, preserving the current rows we have. We can ensure that the dataset is merged correctly by listing all the columns and seeing our added WEO columns at the end.
latam_carribean_weo <- latam_carribean %>%left_join(weo, by =c("iso_a3"="iso3"))#Inspect the resultnames(latam_carribean_weo)
Now let’s map PPP GDP per capita as a color gradient, also adding in country labels.
# Advanced map showing GDP per capita from the WEO dataset ggplot(data = latam_carribean_weo) +# Add countries with color gradient representing GDP per capita (ngdppc)geom_sf(aes(fill = ngdp_r_ppp_pc), color ="white", size =0.2) +# Define the color gradient for GDP per capitascale_fill_gradient(low ="lightblue", high ="darkblue", # Gradient colorsname ="GDP per capita"# Legend title ) +# Add country labels using ISO codesgeom_text(data = latam_carribean_weo, aes(label = iso_a3, geometry = geometry), # ISO country codes as labelsstat ="sf_coordinates", # Extract coordinates for labelssize =2.5, # Label sizecolor ="black", # Label colorcheck_overlap =TRUE# Avoid overlapping labels ) +# Add title, subtitle, and captionlabs(title ="Real GDP per Capita in Latin America and the Caribbean", # Main titlesubtitle ="Per capita, in PPP international currency (WEO 2023)", # Subtitle for contextcaption ="Source: IMF WEO (2023), Natural Earth"# Updated data source ) +# Apply a clean theme for a minimalist designtheme_void() +# Removes gridlines, axis labels, and ticks# Customize the theme for titles, caption, and legendtheme(plot.title =element_text(size =16, face ="bold", hjust =0.5), # Center-align and style titleplot.subtitle =element_text(size =12, hjust =0.5), # Center-align and style subtitleplot.caption =element_text(size =10, hjust =0), # Align caption to the leftlegend.position ="bottom", # Position legend at the bottomlegend.title =element_text(size =10, face ="bold"), # Bold legend title for emphasislegend.text =element_text(size =9), # Adjust legend text size for readabilitypanel.background =element_rect(fill ="white", color =NA) # White background for a clean look )
Formatting and adding the IMF Style
Our map is almost complete, but there is some additional formatting we should do. Let’s expand the legend so that it is more visible, and load and apply the IMF theme.
# Load IMF theme (gives us 'blue' and other style helpers)source(here::here("utils/theme_and_colors_IMF.R"))# Advanced map showing GDP per capita from the WEO dataset ggplot(data = latam_carribean_weo) +# Add countries with color gradient representing GDP per capita (ngdp_r_ppp_pc)geom_sf(aes(fill = ngdp_r_ppp_pc), color ="white", size =0.2) +# Define the color gradient for GDP per capita, with a custom guidescale_fill_gradient(low ="lightblue", high ="darkblue", name ="GDP per capita", guide =guide_colorbar(barwidth =15, # Increase width to stretch out the colorbarbarheight =0.5# Decrease height for a slimmer bar ) ) +# Add country labels using ISO codesgeom_text(data = latam_carribean_weo, aes(label = iso_a3, geometry = geometry), stat ="sf_coordinates", size =2.5, color ="black", check_overlap =TRUE ) +# Add title, subtitle, and captionlabs(title ="Real GDP per Capita in Latin America and the Caribbean", subtitle ="Per capita, in PPP international currency (WEO 2023)",caption ="Source: IMF WEO (2023), Natural Earth" ) +# Remove gridlines, axis labels, and tickstheme_void() +# Override the title/subtitle with IMF stylingtheme(plot.title =element_text(size =16, face ="bold", color = blue, hjust =0.5),plot.subtitle =element_text(size =12, color = blue, hjust =0.5),plot.caption =element_text(size =10, hjust =0), # Legend formattinglegend.position ="bottom",legend.title =element_text(size =9, face ="plain"), # Slightly smaller, no boldlegend.text =element_text(size =8), # Smaller text for numberslegend.key.size =unit(0.4, "cm"), # Control key box size# White backgroundpanel.background =element_rect(fill ="white", color =NA) )
You can now save the map as a high-quality image or PDF for presentation or reports. Check out the images you save to see your map in more detail than is shown on the website.
# Save the map using the here libraryggsave(here("Figures/latam_population_density.png"), dpi =300, width =10, height =8)ggsave(here("Figures/latam_population_density.pdf"), device = cairo_pdf, dpi =300, width =10, height =8)
You now know how to load and filter spatial data, create basic maps, and add thematic features like gradients and annotations.