Skip to content

Instantly share code, notes, and snippets.

@dakvid
Created November 23, 2021 22:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dakvid/56db7b0a41b426e75d199dcf73d86a6e to your computer and use it in GitHub Desktop.
Save dakvid/56db7b0a41b426e75d199dcf73d86a6e to your computer and use it in GitHub Desktop.
#30DayMapChalleng 2021 - Day 24 - Historical
# Make a world map of exports from NZ, with Pacific centred
# For #30DayMapChallenge 2021 - Day 24 - Historical
# -- David Friggens, November 2021
# Map style inspired by @richard_vogg
# https://github.com/richardvogg/30DayMapChallenge21
library(magrittr)
library(readxl)
library(dplyr)
library(sf)
library(countrycode)
library(rnaturalearth)
library(ggplot2)
library(ggflags)
library(ggrepel)
PLOT_FONT <- "Nunito Sans"
BG_COLOUR <- "grey20"
LAND_COLOUR <- "white"
LINE_COLOUR <- "#dfbf81"
# Data from my colleague, but originally from Stats NZ
onions <-
read_excel("trade/Export charts for report.xlsx",
sheet = "Top 20 countries",
range = "A5:B50",
col_names = FALSE) %>%
set_names(c("country", "value")) %>%
mutate(value = round(value / 1000000, 1)) %>%
arrange(desc(value)) %>%
head(20) %>%
mutate(iso_a3 = countrycode(country, origin = "country.name", destination = "iso3c"))
# Medium needed for get coordinates for small countries
# But I'll only plot the small scale
world_medium <-
ne_countries(scale = "medium", returnclass = "sf") %>%
filter(iso_a3 != "ATA") %>% #filter out Antartica
select(sovereignt, continent, iso_a3)
world_small <-
ne_countries(scale = "small", returnclass = "sf") %>%
filter(iso_a3 != "ATA") %>% #filter out Antartica
select(sovereignt, continent, iso_a3)
# Get coordinates of countries for lines and circles
nz_c <-
world_medium %>%
filter(iso_a3 == "NZL") %>%
st_centroid() %>%
select(nzl = iso_a3,
nzl_c = geometry)
destination_c <-
world_medium %>%
inner_join(onions, by = "iso_a3") %>%
st_centroid(of_largest_polygon = TRUE) %>%
# ISO2 needed for flags
mutate(iso_a2 = iso_a3 %>% countrycode(origin = "iso3c", destination = "iso2c") %>% str_to_lower(),
exports_display = glue("${value}m")) %>%
select(iso_a3,
iso_a2,
exports = value,
exports_display,
dest_c = geometry)
# Easy to make straight lines...
onion_lines <-
onions %>%
mutate(nzl = "NZL") %>%
inner_join(nz_c, by = "nzl") %>%
inner_join(destination_c, by = "iso_a3") %>%
rowwise() %>%
mutate(geom = st_union(nzl_c, dest_c) %>% st_cast("LINESTRING")) %>%
ungroup() %>%
select(-nzl_c, -dest_c) %>%
st_as_sf()
# ...and surprisingly easy to turn them into great circles!
# Thanks Jesse Sadler https://www.jessesadler.com/post/great-circles-sp-sf/
onion_gc_lines <-
onion_lines %>%
st_segmentize(units::set_units(20, km))
# Easy to recentre the projection but it is a disaster if any polygons are split.
# I'm sure I saw a blog post recently that mentioned how to fix it, but can't find it now.
# But since I don't need Greenland or Iceland it's easy enough just to take them out. :-)
world_small2 <-
world_small %>%
filter(! iso_a3 %in% c("GRL", "ISL")) %>%
st_transform("+proj=patterson +lon_0=160")
# proportionately sized circles were ok, but tricky with labels
# but proportionately sized flags were no good
gg_onion <-
ggplot() +
geom_sf(data = world_small2,
fill = LAND_COLOUR,
size = 0.1) +
geom_sf(data = onion_gc_lines,
colour = LINE_COLOUR) +
# geom_sf(data = destination_c,
# aes(size = exports),
# colour = LINE_COLOUR) +
geom_label_repel(data = destination_c,
stat = "sf_coordinates",
aes(label = exports_display,
geometry = dest_c),
size = 10,
family = PLOT_FONT,
colour = BG_COLOUR) +
geom_flag(data = destination_c,
stat = "sf_coordinates",
aes(country = iso_a2,
geometry = dest_c),
size = 12) +
coord_sf(datum = NA) +
labs(title = "New Zealand Onion Exports 2020: Top 20 Countries (94%)",
subtitle = "#30DayMapChallenge 20201 - Day 24 - Historical",
caption = "Map: David Friggens @dakvid. Data: StatsNZ",
x = NULL, y = NULL) +
theme_bw() +
theme(plot.background = element_rect(fill = BG_COLOUR, colour = BG_COLOUR),
panel.background = element_rect(fill = BG_COLOUR, colour = BG_COLOUR),
legend.position = "none",
plot.title = element_text(size = 72, family = PLOT_FONT, colour = LINE_COLOUR, hjust = 0.5),
plot.subtitle = element_text(size = 32, family = PLOT_FONT, colour = LINE_COLOUR, hjust = 0.5),
plot.caption = element_text(size = 28, family = PLOT_FONT, colour = LINE_COLOUR))
ggsave(plot = gg_onion,
path = "Day_24", filename = "Day_24_onions.png", device = "png",
width = 40, height = 20, dpi = 72)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment