library(dplyr)
library(ggplot2)
library(sf)
library(janitor)
library(tidyverse)
library(tmap)
library(lubridate)
library(gganimate)
Data sources:
iowa.sf <- st_read('data/county') %>%
clean_names() %>%
st_simplify(dTolerance = 500)
## Reading layer `county' from data source `C:\Users\pvill\repos\random\data\county' using driver `ESRI Shapefile'
## Simple feature collection with 99 features and 10 fields
## geometry type: POLYGON
## dimension: XY
## bbox: xmin: 202073.8 ymin: 4470598 xmax: 736849.2 ymax: 4822674
## projected CRS: NAD83 / UTM zone 15N
month_to_number <- function(x) {
x <- tolower(substr(x, 1, 3))
match(tolower(x), tolower(month.abb))
}
county_pops <- read_csv('data/City_Population_in_Iowa_by_County_and_Year.csv') %>%
clean_names() %>%
separate('year', c('month', 'day', 'year'), sep = ' ') %>%
mutate(year = as.integer(year),
month = month_to_number(month),
day = as.integer(day),
estimate = as.integer(estimate),
county = replace(county, county == "O'Brien", "Obrien"))
## Parsed with column specification:
## cols(
## FIPS = col_double(),
## County = col_character(),
## City = col_character(),
## Year = col_character(),
## Estimate = col_double(),
## `Primary Point` = col_character()
## )
Summarizing the county population data by year and county so that we can join it to iowa.sf
. We also add a column for percentage change over last year because population stays roughly the same within counties, which doesn’t make for very interesting graphs.
county_by_year <- county_pops %>%
group_by(county, year) %>%
summarise(total_pop = sum(estimate, na.rm = TRUE)) %>%
mutate(lag = lag(total_pop),
pct.change = (total_pop - lag) / lag)
## `summarise()` regrouping output by 'county' (override with `.groups` argument)
Adding county populations to the iowa.sf object.
iowa.sf <- inner_join(iowa.sf, county_by_year, by = 'county')
Visualizing counties and population using tmap.
iowa.sf %>%
tm_shape() +
tm_fill(
col = 'total_pop',
title = "Total Population (2018)"
) +
tm_borders(lwd = 0.5) +
tm_text('county', size = 0.6) +
tm_layout(
"Ames Counties",
inner.margins = c(0.08, 0.08, 0.08, 0.08),
legend.position = c('left', 'bottom'),
legend.title.size = 1,
title.position = c("center", "top"),
) +
tm_credits("Source: https://data.iowa.gov/Community-Demographics/City-Population-in-Iowa-by-County-and-Year/y8va-rhk9",
position = c(0.37, 0.0))
Animation of total population over 2011 - 2018. We drop 2010 because there is no percentage change data for that year.
iowa.sf %>%
filter(year > 2010) %>%
ggplot(aes(fill = total_pop)) +
geom_sf() +
ggthemes::theme_map() +
labs(
title = "Ames population by county",
subtitle = "Year: { current_frame }",
caption = "Source: https://data.iowa.gov/Community-Demographics/City-Population-in-Iowa-by-County-and-Year/y8va-rhk9"
) +
scale_fill_gradient2(low = 'blue', mid = 'white', high = 'red') +
theme(
plot.title = element_text(hjust = 0.5, size = 14),
plot.subtitle = element_text(hjust = 0.5, size = 12),
legend.title = element_blank(),
legend.background = element_rect(colour = 'black', fill = 'white'),
panel.background = element_rect(fill = 'gray95')
) +
transition_manual(year) +
geom_sf_text(aes(label = county), size = 2.25)
## nframes and fps adjusted to match transition
##
Rendering [=========================>------------------------------------------------------------------------------] at 7.2 fps ~ eta: 1s
Rendering [======================================>-----------------------------------------------------------------] at 6.7 fps ~ eta: 1s
Rendering [===================================================>----------------------------------------------------] at 6.2 fps ~ eta: 1s
Rendering [=================================================================>----------------------------------------] at 6 fps ~ eta: 1s
Rendering [===============================================================================>--------------------------] at 6 fps ~ eta: 0s
Rendering [============================================================================================>-------------] at 6 fps ~ eta: 0s
Rendering [==========================================================================================================] at 6 fps ~ eta: 0s
##
Frame 1 (12%)
Frame 2 (25%)
Frame 3 (37%)
Frame 4 (50%)
Frame 5 (62%)
Frame 6 (75%)
Frame 7 (87%)
Frame 8 (100%)
## Finalizing encoding... done!
Not very exciting because population stays pretty constant over years:
iowa.sf %>%
filter(county %in% sample(unique(iowa.sf$county), 20)) %>%
ggplot(aes(year, total_pop)) +
geom_col() +
facet_wrap(~ county, scales = "free_y") +
theme(axis.text.y = element_blank(),
axis.text.x = element_text(angle = 90)) +
labs(x = element_blank(),
title = "Population in Ames counties from 2011 to 2018"
) +
scale_x_continuous(breaks = 2010:2018)
Mapping percentage change instead:
iowa.sf %>%
filter(year > 2010) %>%
ggplot(aes(fill = pct.change)) +
geom_sf() +
ggthemes::theme_map() +
labs(title = "Percent change in Ames population by county",
subtitle = "Year: { current_frame }",
caption = "Source: https://data.iowa.gov/Community-Demographics/City-Population-in-Iowa-by-County-and-Year/y8va-rhk9"
) +
scale_fill_gradient2(low = 'blue', mid = 'white', high = 'red',
na.value = 'white'
) +
theme(
plot.title = element_text(hjust = 0.5, size = 14),
plot.subtitle = element_text(hjust = 0.5, size = 12),
legend.title = element_blank(),
legend.background = element_rect(colour = 'black', fill = 'white'),
panel.background = element_rect(fill = 'gray95')
) +
transition_manual(year) +
geom_sf_text(aes(label = county), size = 2.25)
## nframes and fps adjusted to match transition
##
Rendering [=========================>------------------------------------------------------------------------------] at 7.2 fps ~ eta: 1s
Rendering [======================================>-----------------------------------------------------------------] at 6.5 fps ~ eta: 1s
Rendering [===================================================>----------------------------------------------------] at 6.4 fps ~ eta: 1s
Rendering [================================================================>---------------------------------------] at 6.3 fps ~ eta: 0s
Rendering [=============================================================================>--------------------------] at 6.2 fps ~ eta: 0s
Rendering [==========================================================================================>-------------] at 6.2 fps ~ eta: 0s
Rendering [========================================================================================================] at 6.1 fps ~ eta: 0s
##
Frame 1 (12%)
Frame 2 (25%)
Frame 3 (37%)
Frame 4 (50%)
Frame 5 (62%)
Frame 6 (75%)
Frame 7 (87%)
Frame 8 (100%)
## Finalizing encoding... done!
We can see by the scale that the percentage change isn’t very large, but at least the animation is more interesting :)
Paul Villanueva
Ph.D. Student - Bioinformatics and Computational Biology
Iowa State University, Ames, IA.