DATA 608 : Do Stricter Gun Laws Reduce Firearm Gun Deaths?

Author: Rupendra Shrestha

Column

Column

Instructions

The CDC publishes firearm mortality for each State per 100,000 persons https://www.cdc.gov/nchs/pressroom/sosmap/firearm_mortality/firearm.htm. 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?”

For this assignment you will need to:

Access the firearm mortality data from the CDC using an available API (https://open.cdc.gov/apis.html)

Create a 5 point Likert scale categorizing gun control laws from most lax to strictest and assign each state to the most appropriate Likert bin.

Determine whether stricter gun control laws result in reduced gun violence deaths

Present your story using heat maps

Introduction

Gun violence remains a persistent and complex public health issue in the United States. Firearm related deaths—encompassing homicides, suicides, and accidental discharges account for a substantial share of preventable mortality each year. Although many factors contribute to this problem, firearm legislation is one of the most debated and potentially influential levers for reducing gun-related deaths. Policymakers and researchers have long questioned whether stricter gun control laws are associated with lower firearm mortality rates across states.

This analysis explores the relationship between the strength of state gun control laws and firearm mortality rates, drawing on publicly available data from the Centers for Disease Control and Prevention (CDC). Using a five-point Likert scale to classify each state’s firearm regulations—from most lax to most strict—this study visualizes how the intensity of gun legislation corresponds with firearm-related death rates. Through heat maps and summary visualizations, the goal is to determine whether stricter firearm control laws are correlated with lower firearm mortality, and to provide a data-driven perspective on how policy differences may shape public safety outcomes across the United States.

Data Load

The data in this section are obtained directly from the CDC’s public API, ensuring that the analysis uses the most current firearm mortality information available. The JSON response is converted into a structured data frame for easier analysis and visualization. This automated loading process enhances reproducibility and eliminates the need for manual downloads or data entry.

Access the firearm mortality data from the CDC using an available API (https://open.cdc.gov/apis.html)
# Set JSON data URL
url <- "https://data.cdc.gov/resource/489q-934x.json"

# Fetch JSON data by sending GET request
response_data <- GET(url)

if (status_code(response_data) == 200) {
  list_data <- fromJSON(content(response_data, "text", encoding = "UTF-8"))
  # Convert list to data frame
  mortality_data <- as.data.frame(list_data)
} else {
  cat("Error: Unable to retrieve data from the URL.\n")
}

#Seeing data details
#str(mortality_data)

#Seeing first 10 rows of data frame
#head(mortality_data,10)
# Example: scrollable, fixed width, with Next/Previous
datatable(
  mortality_data,
  options = list(
    scrollX = TRUE,         # enables horizontal scrolling
    autoWidth = TRUE,       # adjusts column widths
    pageLength = 10,         # rows per page
    columnDefs = list(
      list(width = '100px', targets = "_all")  # fixed width per column
    )
  ),
  caption = "Scrollable Table with Pagination and All Columns Visible"
)

Data Preparation

In this section, the dataset is filtered to include only records related to firearm-related injuries with crude mortality rates. The data are then reshaped into a long format to align state names with their corresponding firearm death rates. Each state is categorized on a five-point Likert scale representing the strictness of its gun control laws, ranging from most lax (1) to most strict (5). These preparation steps ensure the dataset is clean, consistent, and ready for meaningful visualization and analysis.

# Load required packages
library(dplyr)
library(tidyr)
library(stringr)
library(DT)

# --- 1. Filter the data for Firearm-related injury and Crude rate
df_gun <- mortality_data %>%
  filter(
    cause_of_death == "Firearm-related injury",
    rate_type == "Crude",
    time_period == "12 months ending with quarter"
  )

# --- 2. Rename state columns (replace long names with abbreviations)
state_abbreviations <- c(
  AL = "alabama", AK = "alaska", AZ = "arizona", AR = "arkansas", CA = "california",
  CO = "colorado", CT = "connecticut", DE = "delaware", FL = "florida", GA = "georgia",
  HI = "hawaii", ID = "idaho", IL = "illinois", IN = "indiana", IA = "iowa",
  KS = "kansas", KY = "kentucky", LA = "louisiana", ME = "maine", MD = "maryland",
  MA = "massachusetts", MI = "michigan", MN = "minnesota", MS = "mississippi", MO = "missouri",
  MT = "montana", NE = "nebraska", NV = "nevada", NH = "new_hampshire", NJ = "new_jersey",
  NM = "new_mexico", NY = "new_york", NC = "north_carolina", ND = "north_dakota",
  OH = "ohio", OK = "oklahoma", OR = "oregon", PA = "pennsylvania", RI = "rhode_island",
  SC = "south_carolina", SD = "south_dakota", TN = "tennessee", TX = "texas", UT = "utah",
  VT = "vermont", VA = "virginia", WA = "washington", WV = "west_virginia", WI = "wisconsin",
  WY = "wyoming", DC = "district_of_columbia"
)

# Replace rate_<state> patterns with state abbreviations
for (abbrev in names(state_abbreviations)) {
  pattern <- paste0("rate_", state_abbreviations[abbrev])
  names(df_gun) <- str_replace_all(names(df_gun), pattern, abbrev)
}

# --- 3. Convert columns 6:69 to numeric and extract year
df_gun <- df_gun %>%
  mutate(across(6:69, as.double)) %>%
  mutate(year = as.numeric(substr(year_and_quarter, 1, 4)))

# --- 4. Filter for 2022 Q4 data
df_gun_2022 <- df_gun %>%
  filter(year_and_quarter == "2022 Q4")

# --- 5. Pivot to long format (State, Rate)
df_gun_2022_long <- df_gun_2022 %>%
  pivot_longer(
    cols = AK:WY,
    names_to = "state",
    values_to = "rate"
  )

# --- 6. Add Gun Law Rank
final_df <- df_gun_2022_long %>%
  transmute(
    year,
    state,
    rate,
    gun_laws = case_when(
      state %in% c("AK", "AL", "AR", "AZ", "GA", "IA", "ID", "IN", "KS", "KY", "LA", "ME", "MO", "MS", "MT", "ND", "NH", "OH", "OK", "SC", "SD", "TN", "TX", "UT", "WV", "WY") ~ 1,
      state == "WI" ~ 2,
      state %in% c("FL", "MI", "MN", "NC", "NE", "NM", "NV", "VT") ~ 3,
      state %in% c("CO", "DE", "OR", "PA", "RI", "VA", "WA") ~ 4,
      state %in% c("CA", "CT", "DC", "HI", "IL", "MA", "MD", "NJ", "NY") ~ 5,
      TRUE ~ NA_real_
    )
  )

# --- 7. Display the final dataset interactively
datatable(
  final_df,
  options = list(scrollX = TRUE, pageLength = 10),
  caption = "Final Dataset: Firearm-related Mortality (2022 Q4) with Gun Law Rank"
)

Heatmap

A heatmap is a powerful visualization tool that allows us to observe patterns and distributions across geographic regions. In this analysis, the heatmap displays the strength of gun control laws across U.S. states for the fourth quarter of 2022. Each state is colored according to its gun law category on a five-point Likert scale, ranging from Most Lax to Most Strict. This visualization makes it easy to identify regional trends, compare states, and explore how the strictness of firearm legislation varies across the country. By combining geographic and categorical information, the heatmap provides an intuitive way to visually assess the relationship between gun laws and firearm related mortality.

library(plotly)

# Ensure gun_laws is numeric (1–5)
final_df$gun_laws <- as.numeric(final_df$gun_laws)

# Define colors (numeric keys)
category_colors <- c(
  "1" = "#3399FF",   # Most Lax (blue)
  "2" = "#66a366",   # Lax (green)
  "3" = "#e6e600",   # Moderate (yellow)
  "4" = "#ffcc80",   # Strict (orange)
  "5" = "#ff6666"    # Most Strict (red)
)

# Create Plotly choropleth with larger size
heatmap <- plot_geo(final_df, locationmode = 'USA-states') %>%
  add_trace(
    locations = ~state,
    z = ~gun_laws,            
    color = ~gun_laws,
    colors = category_colors,
    text = ~paste0(
      "State: ", state,
      "<br>Category: ", gun_laws,
      "<br>Death Rate: ", round(rate, 2)
    ),
    hoverinfo = "text"
  ) %>%
  layout(
      title = list(
      text = "<b>Gun Laws Strength by US State (2022 Q4)</b>",
      x = 0.5,                # center title
      xanchor = "center"
    ),
    geo = list(
      scope = 'usa',
      projection = list(type = 'albers usa'),
      showlakes = TRUE,
      lakecolor = toRGB('white')
    ),
    width = 800,    # Increase width
    height = 500     # Increase height
  ) %>%
  colorbar(
    title = "Level of Strictness in Gun Control Laws",
    tickvals = 1:5,
    ticktext = c("Most Lax", "Lax", "Moderate", "Strict", "Most Strict"),
    ticks = "outside"
  )

# Show heatmap
heatmap

The heatmap reveals clear geographic patterns in gun law strictness across the United States. States with the most lax firearm regulations tend to cluster in certain regions, while states enforcing stricter laws are often found in others. By visualizing these categories alongside firearm mortality rates in hover text, the heatmap provides immediate insights into potential correlations between legislation and death rates. Overall, the heatmap highlights the importance of geographic context in understanding how state-level gun control laws differ and offers a compelling visual story for policymakers and the public about the landscape of firearm regulation in the U.S.

Firearm Mortality Rate by Gun Laws Strength Category

This analysis examines how firearm mortality rates vary across states with different levels of gun law strictness. States are grouped into five categories, from Most Lax to Most Strict, and the average death rate for each category is calculated. The bar chart and table provide an easy way to compare these rates and see how gun law strength relates to firearm deaths.

# Calculate average firearm death rate for each gun law category
avg_rate_by_category <- final_df %>%
  group_by(gun_laws) %>%
  summarize(Average_Rate = mean(rate, na.rm = TRUE))  # Remove NAs if any

# Define a visually appealing color palette (blue → red)
category_colors <- c(
  "1" = "#3399FF",   # Most Lax - Blue
  "2" = "#66CC66",   # Lax - Green
  "3" = "#FFCC33",   # Moderate - Yellow
  "4" = "#FF9933",   # Strict - Orange
  "5" = "#FF3333"    # Most Strict - Red
)

# Ensure gun_laws is factor for consistent ordering
avg_rate_by_category$gun_laws <- factor(avg_rate_by_category$gun_laws, levels = 1:5)

# Create Plotly bar chart
bar_chart <- plot_ly(
  avg_rate_by_category,
  x = ~gun_laws,
  y = ~Average_Rate,
  type = 'bar',
  marker = list(color = ~gun_laws, colors = category_colors),
  text = ~paste("Category:", gun_laws, "<br>Average Rate:", round(Average_Rate, 2)),
  hoverinfo = "text"
) %>%
  layout(
    title = list(
      text = "<b>Average Firearm Mortality Rate by Gun Law Category (2022 Q4)</b>",
      x = 0.5,                # center title
      xanchor = "center"
    ),
    xaxis = list(title = "Gun Laws Strength Category"),
    yaxis = list(title = "Average Firearm Mortality Rate"),
    showlegend = FALSE,
    plot_bgcolor = "#f9f9f9", # Light background for aesthetics
    paper_bgcolor = "#f9f9f9",
    width = 800,   # control width (default ~900)
    height = 500   # control height (default ~600)
  )

# Show bar chart
bar_chart
Average Firearm Mortality Rate by Gun Laws Strength Category
gun_laws Average_Rate
Most Lax 19.13
Lax 14.10
Moderate 16.02
Strict 13.14
Most Strict 9.44

The bar chart shows that states with more lenient gun laws generally have higher firearm mortality rates, while states with stricter laws tend to have lower rates. This suggests that stricter gun control is associated with reduced firearm deaths, although other factors may also play a role.

Conclusion

The visualizations reveal a pattern where states characterized by more lenient gun laws tend to exhibit higher rates of firearm-related deaths, whereas states enforcing the most stringent gun laws demonstrate the lowest death rates. In general, the bar chart suggests an association between stricter gun control laws and reduced mortality rates, with a minor anomaly: states with highly stringent gun laws show a slightly elevated death rate compared to those with moderately strengthened laws. This anomaly may be attributed to unaccounted factors that differ across states in this analysis. To sum up, it can be concluded that the implementation of stricter firearm control laws contributes to a decline in firearm mortality rates in U.S. states.