29 Population

A classic theme for a map.

Given the recent release of approved population grids data by Statistics New Zealand, it seems an apt moment for the by-now classic Joy Division Unknown Pleasures ‘ridge lines’ map of population. No use trying this in tmap, but there is a package ggridges that handles it nicely.

Libraries

Code
library(sf)
library(dplyr)
library(ggplot2)
library(ggridges)
library(terra)

Data wrangling

The population grids are much too high resolution for this to work for the whole country, so I convert them to rasters to enable simple reaggregation, and then remake them as points which is what ggridges wants.

After some experimentation I found a 20km2 (80 x 250m) resolution was about right. I also rescaled the population numbers to get the vertical movement in the ‘ridgelines’ that I wanted.

Code
pop <- st_read("data/nz-pop-grid-250m.gpkg") %>%
  filter(CENTROID_X < 2.25e6)

grid <- pop %>%
  st_buffer(3e4) %>%
  st_bbox() %>%
  st_as_sfc(crs = 2193) %>%
  st_sf() %>%
  as("SpatVector") %>%
  rast(resolution = 250)

pop_grid <- pop %>%
  rasterize(grid, field = "ERP_2022", background = 0)

pop_grid_agg <- pop_grid %>%
  aggregate(c(80, 8), fun = "sum", na.rm = TRUE)

pts <- pop_grid_agg %>%
  as.points() %>%
  st_as_sf()

pop_pts <- pts %>%
  st_coordinates() %>%
  as_tibble() %>%
  mutate(Population = pts$ERP_2022 * 2.5)

The map

After some messing around on my own with geom_line and geom_ribbon, it’s clear that there is some fiddliness involved in rendering the lines in the right order (from top to bottom, back to front) and also in positioning the ‘filled area’ in the correct place relative to the line atop it. It was then that I threw in the towel on my own implementation (shoulders of giants and all that) and downloaded ggridges.

As you can see, to a first order approximation, nobody lives in New Zealand, or at any rate, they all live in Auckland.

ggplot(pop_pts, aes(x = X, y = Y, group = Y, height = Population)) +
  geom_ridgeline(fill = "black", colour = "white", 
                 size = 1.5 * 25.4 / 72.27) +
  coord_equal(expand = FALSE) +
  theme_void() +
  theme(panel.background = element_rect(fill = "black"),
        plot.background = element_rect(fill = "black"))