There are several different ways to make maps in R, and I always have to look it up and figure this out again from previous examples that I’ve used. Today I had another look at what’s currently possible and what’s an easy way of making a world map in ggplot2 that doesn’t require fetching data from various places.

TLDR: Copy this code to plot a world map using the tidyverse:

``````library(tidyverse)
library(ggthemes)

world_map = map_data("world") %>%
filter(! long > 180)

countries = world_map %>%
distinct(region) %>%
rowid_to_column()

countries %>%
ggplot(aes(fill = rowid, map_id = region)) +
geom_map(map = world_map) +
expand_limits(x = world_map\$long, y = world_map\$lat) +
coord_map("moll") +
theme_map()`````` # Explanation

To make a map using `geom_map()` you’ll need two datasets: one that includes the map data (country borders), and another one on how to colour in each area. I tried doing `data = NULL` or `fill = "grey"` to make all countries the same colour, but couldn’t get that to work. So I’m creating the necessary second dataset with `distinct(world_map, region)` which is a list of every country from the map data. This list of countries (=regions) is the first argument to `ggplot()`, the `world_map` data goes inside `geom_map()`. `expand_limits()` are essential as otherwise you will not see anything.

``````library(tidyverse)

# Load map data
world_map = map_data("world")

distinct(world_map, region) %>%
ggplot(aes(map_id = region)) +
geom_map(map = world_map) +
expand_limits(x = world_map\$long, y = world_map\$lat)`````` # Equal area projection

Global maps that do not use an equal area projection are a huge pet peeve of mine. The above map is not ‘equal-area’ and the closer to the equator an area is the more diminished it is.

Let’s just plot Greenland and Algeria for example:

``````tibble(region = c("Greenland", "Algeria")) %>%
ggplot(aes(map_id = region)) +
geom_map(map = world_map) +
expand_limits(x = world_map\$long, y = world_map\$lat)`````` In reality, Algeria is bigger than Greenland: 2.4 million km2 vs 2.2 million km2!

Therefore, I always use an equal-area projection such as Mollweide:

``````library(tidyverse)

# Load map data
world_map = map_data("world")

distinct(world_map, region) %>%
ggplot(aes(map_id = region)) +
geom_map(map = world_map) +
expand_limits(x = world_map\$long, y = world_map\$lat) +
coord_map("moll")`````` But then we get those weird lines in the Northern Hemisphere. That’s because parts of the US and Russia extend across the 180th meridian. And since `geom_map()` is connecting each area with itself it then draws these lines across the globe.

A simple fix I’ve found is to remove map data that has a longitude greater than 180 degrees:

``````library(tidyverse)
library(ggthemes)

world_map = map_data("world") %>%
filter(! long > 180)

countries = world_map %>%
distinct(region) %>%
rowid_to_column()

countries %>%
ggplot(aes(fill = rowid, map_id = region)) +
geom_map(map = world_map) +
expand_limits(x = world_map\$long, y = world_map\$lat) +
coord_map("moll") +
theme_map()`````` I’ve also thrown in `theme_map()` from `library(ggthemes)`, put the coutry list which I made with `distinct()` into a separate object, and added in `fill = rowid` for some colour. This is useful as I’m generally plotting chloropleths so I want a tibble with values for each country that I can join with whatever data I have for each country (e.g., student numbers, population, etc.).