The CDC publishes firearm mortality for each State per 100,000 persons. Each State’ firearm control laws can be categorized as very strict to very lax. The purpose of this Story is to answer the question, “Do stricter firearm control laws help reduce firearm mortality?”
# libraries
library('tidyverse')
library('readxl')
library('httr2')
library('tidyjson')
library('RColorBrewer')
library('sf')
library('rnaturalearth')
library('rnaturalearthdata')
# ggplot
theme_set(theme_light())
To assemble this data I relied on two sources – the CDC’s Quarterly Provisional Estimates for Selected Indicators of Mortality, and Boston University’s State Firearm Laws database.
The CDC dataset was accessed via a simple API request (using httr), and the json-formatted response converted to an R dataframe for easier handling (using tidyjson.) I selected the 12-month period ending in 2021-Q1 to align with the date range of information available in the State Firearm Laws dataset.
# api request - cached
req <- request('https://data.cdc.gov/resource/489q-934x.json')
resp <- req_perform(req)
# mortality df
mortality_df <- resp %>%
resp_body_json %>%
spread_all() %>%
as.data.frame() %>%
filter(year_and_quarter == '2021 Q1',
time_period == '12 months ending with quarter',
cause_of_death == 'Firearm-related injury',
rate_type == 'Crude') %>%
select(c(10:60)) %>%
rename_with(~ gsub("rate_", "", .x)) %>%
pivot_longer(cols=everything(), names_to = 'state', values_to = 'rate') %>%
mutate(state = gsub("_", " ", state),
state = tools::toTitleCase(state),
rate = as.numeric(rate))
This dataset was downloaded directly from the State Firearm Laws project site, and filtered for the year 2020. This is a very simplified dataset tabulating the number of firearms-restrictive laws in effect at a state level for a given time period. The only main caveat here is the exclusion of territories and federal regions such as the District of Colombia.
I applied a quantile with five levels to create a “Restriction Level” variable, where 1 represented the least-regulated environment and 5 the most-regulated environment, based on the number of restrictive firearms laws in effect.
# laws df
laws_df <- read_excel('data/bu_state_firearm_laws.xlsx', sheet='DATABASE') %>%
filter(year == '2020') %>%
mutate(rank = as.numeric(cut(lawtotal,
breaks = quantile(lawtotal, probs = 0:5/5),
include.lowest = TRUE,
labels = 1:5))) %>%
select(c('state','lawtotal','rank'))
# all data
df <- left_join(mortality_df, laws_df, by='state')
Other sources for Firearms Laws data were also considered, such as the Rand Gun Policy database - however that longitudinal survey data (which includes on both pro- and anti-gun legislation) seemed more complex than necessary for this project.
For visualization I chose to use ggplot with Naturalearth shapefiles, using Simple Features (sf) to wrangle the spatial data.
# get map shapefile from naturalearth
us_states <- ne_states(country = "United States of America", returnclass = "sf")
us_states <- us_states %>% filter(name != 'Alaska', name != 'Hawaii')
us_states_data <- merge(us_states, df, by.x = "name", by.y = "state")
# min and max rates for nicer legend
rate_min = min(us_states_data$rate)
rate_max = max(us_states_data$rate)
# plot
ggplot(data = us_states_data) +
geom_sf(aes(fill = rate, size = rank)) +
geom_sf_label(aes(label=rank), fill='grey') +
coord_sf(datum = NA) +
theme(axis.title.x = element_blank(),
axis.title.y = element_blank(),
legend.box = 'vertical',
legend.position = 'bottom'
) +
labs(fill = "Deaths per 100k",
size = "Restriction Level",
title = "Firearms Restrictions and Deaths by State, 2020",
subtitle = 'States with stronger firearms laws tend to suffer fewer firearms-related deaths per capita') +
scale_colour_distiller(
palette = 'Oranges',
aesthetics = 'fill',
direction = 1,
labels = c(rate_min, rate_max),
breaks = c(rate_min+1.5, rate_max-1.5)) + # nudge legend labels
scale_size(breaks=c(1,2,3,4,5))
One issue I did not manage to resolve was the handling of the Alaska and Hawaii polygons due to their distance (and Alaska’s relative size). One approach I tried to pursue was the use of “Albers” projections which resize and orient these two states directly underneath the continental US, as commonly seen in electoral projection maps. However the most popular R library for this task (AlbersUSA) is outdated and not actively maintained – for now, I chose to omit the Alaska and Hawaii data from this graph.
Based on the data observed, there does appear to be a relationship between per-capita firearm-related deaths and a broad measure of restrictive firearms laws at the state level. States that rated a 4 or 5 (that is, having 35 or more laws in effect) tended to have the lowest rates of firearm-related deaths, while states with the lowest ratings tended to have higher rates of firearm-related deaths.
Of course, this is a very broad finding and it would be interesting to examine some of the deeper relationships and understand the efficacy of certain types of legislation such as background checks and waiting periods, gun buyback programs, and so forth. It would also be interesting to explore some of the edge cases such as Louisiana, Tennessee and the District of Colombia where firearms legislation is in effect but high incidence rates are still observed.