Puerto Rico Cartogram

Jody Holland

Introduction

The aim of this mini project is make some fun cartograms of Puerto Rico!

library(tidyverse)
library(broom)
library(sf)
library(ggthemes)
library(ggplot2)
library(cartogram)
library(tweenr)    
library(gganimate)
library(sp)

Loading data

The first dataset I am using is Geodata regarding Puerto Rico. This data was very hard to find.

districts <- st_read("map.json") # load as sf object
## Reading layer `map' from data source 
##   `C:\Users\jodyh\Desktop\islands_projects\pr_pop\map.json' using driver `GeoJSON'
## Simple feature collection with 78 features and 13 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -67.95181 ymin: 17.88264 xmax: -64.99986 ymax: 18.51597
## Geodetic CRS:  WGS 84

Next is loading the population data

population <- read.csv("data.csv") %>% as_tibble() # load as tibble for binding

Now I have to prepare the data and calculate the cartogram

toplot_base <- left_join(districts, population, by = c("id_1" = "id")) %>%
  st_transform(crs = 3857) # load with a mercator project
toplot_base$X2019 <- as.double(toplot_base$X2019) # make sure is a number

toplot2019 <- toplot_base %>% select(c("id",
                                       "X2019",
                                       "geometry"))
toplot_plain <- toplot_base %>% select(c("id",
                                       "X2019",
                                       "geometry"))
toplot_end <- toplot_plain # create the frames

toplot_plain$frame <- "a"
toplot2019$frame <- "b"
toplot_end$frame <- "c" # give the frames identities

toplot2019 <- toplot2019 %>% cartogram_cont(weight = "X2019") # calculate 

data <- rbind(toplot_plain, toplot2019, toplot_end)

Making Plots

Now I make the plots, one static, one animated

ggplot(toplot2019, aes(fill = X2019)) + # load data into plot
  geom_sf(size = 0) + # remove borders
  theme_void() +
  scale_fill_viridis_b(option = "B", # format scale and legend
                       breaks = c(50000, 100000, 150000, 200000),
                       labels = c("50000", "100000", "150000", "200000"),
                       guide = guide_legend(title = "Population",
                                            keyheight = unit(3, units = "mm"),
                                            keywidth=unit(12, units = "mm"),
                                            label.position = "bottom",
                                            title.position = 'top', nrow=1)) + 
  theme(
    legend.position = "bottom", # put key at the bottom
    plot.background = element_rect(fill = "#D2D2CF", color = NA),
    panel.background = element_rect(fill = "#D2D2CF", color = NA), 
    legend.background = element_rect(fill = "#D2D2CF", color = NA), 
  ) +
  coord_sf()

Now I make the animated plot using gganimate

p <- ggplot(data, aes(fill = X2019)) +
  geom_sf(size = 0) + # remove borders
  theme_void() +
  scale_fill_viridis_b(option = "B", # format scale and legend
                       breaks = c(50000, 100000, 150000, 200000),
                       labels = c("50000", "100000", "150000", "200000"),
                       guide = guide_legend(title = "Population",
                                            keyheight = unit(3, units = "mm"),
                                            keywidth=unit(12, units = "mm"),
                                            label.position = "bottom",
                                            title.position = 'top', nrow=1)) + 
  theme(legend.position = "bottom", # put key at the bottom
        plot.background = element_rect(fill = "#D2D2CF", color = NA),
        panel.background = element_rect(fill = "#D2D2CF", color = NA),
        legend.background = element_rect(fill = "#D2D2CF", color = NA)) +
  coord_sf() +
  transition_states(frame,
                    transition_length = 2,
                    state_length = 1) + # code frames
  ease_aes('sine-in-out')

anim_save(animation = p,
          "cart.gif",
          renderer = gifski_renderer(),
          res = 1080,
          width = 3,
          height = 2,
          units = "in") # save as gif