Crash Exposure and Rates Explained

On this page

Problem statement

A crash rate is deaths divided by something, and the something decides the answer. Divide by residents and you measure how many people a place loses; by licensed drivers, how dangerous driving is for those allowed to do it; by registered vehicles, how often a vehicle is involved; by vehicle miles travelled, how often travel ends in a death. Each is called "the" crash rate somewhere, and they rank places differently. Choosing among them is choosing a question.

This page computes all four for the 50 US states and the District of Columbia in 2023, from FARS deaths, Census population estimates and three Federal Highway Administration tables: licensed drivers (DL-22), registered vehicles (MV-1) and vehicle miles (VM-2). It compares the rankings and finds the states whose position depends most on the denominator.

Quick answer

Put deaths and the four denominators in one table, keyed by state name, and compute each rate:

R = DEN.join(DEATHS)
R["per_100k_residents"] = R.deaths / R.residents * 1e5
R["per_100k_drivers"] = R.deaths / R.drivers * 1e5
R["per_100k_vehicles"] = R.deaths / R.vehicles * 1e5
R["per_100m_miles"] = R.deaths / (R.vmt_millions * 1e6) * 1e8
RATES = ["per_100k_residents", "per_100k_drivers", "per_100k_vehicles", "per_100m_miles"]
us = R.sum()
print(f"US: {us.deaths / us.residents * 1e5:.1f} per 100k residents, {us.deaths / us.drivers * 1e5:.1f} per 100k drivers, "
      f"{us.deaths / us.vehicles * 1e5:.1f} per 100k vehicles, {us.deaths / (us.vmt_millions * 1e6) * 1e8:.2f} per 100M miles")
print(R[RATES].rank(ascending=False).astype(int).sort_values("per_100k_residents").head(5).to_string())
US: 12.2 per 100k residents, 17.3 per 100k drivers, 14.4 per 100k vehicles, 1.26 per 100M miles
                per_100k_residents  per_100k_drivers  per_100k_vehicles  per_100m_miles
Mississippi                      1                 1                  1               1
Wyoming                          2                 2                 18              12
New Mexico                       3                 3                  3               8
South Carolina                   4                 8                  6               3
Arkansas                         5                 6                 14              10

The same 41,025 deaths give 12.2 per 100,000 residents, 17.3 per 100,000 licensed drivers, 14.4 per 100,000 vehicles and 1.26 per 100 million miles. Mississippi is worst on all four. Wyoming, second per resident and per driver, is 18th per vehicle and 12th per mile.

Slope chart of the 50 states and DC ranked by 2023 road death rate per resident, per licensed driver, per registered vehicle and per vehicle mile: Mississippi is first on all four; Wyoming goes from 2nd to 18th per vehicle and 12th per mile; Montana from 8th to 47th per vehicle and back to 11th per mile; Delaware from 25th to 2nd per vehicle; the District of Columbia from 47th per resident to 26th per mile; New York from 50th to 29th per vehicle and 44th per mile. Slope chart of the 50 states and DC ranked by 2023 road death rate per resident, per licensed driver, per registered vehicle and per vehicle mile: Mississippi is first on all four; Wyoming goes from 2nd to 18th per vehicle and 12th per mile; Montana from 8th to 47th per vehicle and back to 11th per mile; Delaware from 25th to 2nd per vehicle; the District of Columbia from 47th per resident to 26th per mile; New York from 50th to 29th per vehicle and 44th per mile.
One set of deaths, four rankings.

Read FHWA tables, compare rankings, find states that move

1. Read the FHWA tables

The FHWA sheets have multi-row headers and state names with footnote markers such as "Alabama (2)", and two of them abbreviate the District of Columbia as "Dist. of Col.". Clean the names, keep the 51 rows that match Census state names, and check that nothing is missing:

print(f"states matched: {len(DEN)}; missing values: {int(DEN.isna().sum().sum())}")
print(f"drivers {DEN.drivers.sum() / 1e6:.1f} million; vehicles {DEN.vehicles.sum() / 1e6:.1f} million; "
      f"VMT {DEN.vmt_millions.sum() / 1e6:.2f} trillion miles; residents {DEN.residents.sum() / 1e6:.1f} million")
states matched: 51; missing values: 0
drivers 237.7 million; vehicles 284.6 million; VMT 3.25 trillion miles; residents 334.9 million

All 51 rows match on all four denominators. The country had 237.7 million licensed drivers, 284.6 million registered vehicles and 3.25 trillion vehicle miles for 334.9 million residents.

2. Compare the rankings

print(R[RATES].corr(method="spearman").round(2).to_string())
                    per_100k_residents  per_100k_drivers  per_100k_vehicles  per_100m_miles
per_100k_residents                1.00              0.98               0.76            0.85
per_100k_drivers                  0.98              1.00               0.77            0.84
per_100k_vehicles                 0.76              0.77               1.00            0.77
per_100m_miles                    0.85              0.84               0.77            1.00

Per resident and per driver are almost the same ranking, 0.98, because drivers are a fairly stable share of residents. Per vehicle agrees least with the others, 0.76 to 0.77.

Rank correlations between four road death rates across US states, 2023. rank correlation between the four ratesdriversvehiclesmilesresidents0.980.760.85drivers0.770.84vehicles0.77Per vehicle disagrees most: registrations vary fivefold per resident spatialworkflow.io
How far the rankings agree.

3. Find the states that move most

ranks = R[RATES].rank(ascending=False)
R["rank_spread"] = ranks.max(axis=1) - ranks.min(axis=1)
print(ranks.assign(spread=R.rank_spread).sort_values("spread", ascending=False).head(6).astype(int).to_string())
print(f"drivers per resident: {(R.drivers / R.residents).min():.2f} to {(R.drivers / R.residents).max():.2f}; "
      f"vehicles per resident: {(R.vehicles / R.residents).min():.2f} to {(R.vehicles / R.residents).max():.2f}")
                      per_100k_residents  per_100k_drivers  per_100k_vehicles  per_100m_miles  spread
Montana                                8                11                 47              11      39
Delaware                              25                30                  2              18      28
District of Columbia                  47                50                 26              26      24
South Dakota                          14                17                 38              19      24
New York                              50                48                 29              44      21
North Dakota                          22                24                 41              36      19
drivers per resident: 0.63 to 0.86; vehicles per resident: 0.43 to 2.08

Montana moves 39 places: 8th per resident, 47th per vehicle, with more than two registered vehicles per resident, the most of any state. Delaware is the reverse, 25th per resident and 2nd per vehicle. Vehicles per resident range almost fivefold, from 0.43 to 2.08, which is why the per-vehicle rate disagrees most.

One state, four rates

The data used on this page

NHTSA's FARS 2023 crash file; the Census Bureau's 2023 state population estimates; and the Federal Highway Administration's Highway Statistics 2023 tables DL-22 (licensed drivers by age), MV-1 (registered vehicles) and VM-2 (vehicle miles travelled).

import re
import zipfile
from pathlib import Path

import pandas as pd
import requests

Path("data").mkdir(exist_ok=True)
H = "https://www.fhwa.dot.gov/policyinformation/statistics/2023/xls/"
SRC = {"FARS2023NationalCSV.zip": "https://static.nhtsa.gov/nhtsa/downloads/FARS/2023/National/FARS2023NationalCSV.zip",
       "NST-EST2023-ALLDATA.csv": "https://www2.census.gov/programs-surveys/popest/datasets/2020-2023/state/totals/NST-EST2023-ALLDATA.csv",
       "dl22_2023.xlsx": H + "dl22.xlsx", "mv1_2023.xlsx": H + "mv1.xlsx", "vm2_2023.xlsx": H + "vm2.xlsx"}
for name, url in SRC.items():
    if not Path("data", name).exists():
        Path("data", name).write_bytes(requests.get(url, timeout=600).content)

clean = lambda s: re.sub(r"\s*\(\d+\)", "", str(s)).strip().replace("Dist. of Col.", "District of Columbia")
pop = pd.read_csv("data/NST-EST2023-ALLDATA.csv").query("SUMLEV == 40")
pop = pop[pop.NAME != "Puerto Rico"].set_index("NAME")
dl = pd.read_excel("data/dl22_2023.xlsx", sheet_name="TOTAL", header=None)
dl = dl.assign(name=dl[0].map(clean)).set_index("name")
drivers = dl.loc[dl.index.isin(pop.index), list(range(1, 16))].astype(float).sum(axis=1)   # 15 age bands
mv = pd.read_excel("data/mv1_2023.xlsx", sheet_name=0, header=None)
mv = mv.assign(name=mv[0].map(clean)).set_index("name")
vehicles = mv.loc[mv.index.isin(pop.index), 15].astype(float)                               # all motor vehicles
vm = pd.read_excel("data/vm2_2023.xlsx", sheet_name="A", header=None)
vm = vm.assign(name=vm[0].map(clean)).set_index("name")
vmt = vm.loc[vm.index.isin(pop.index), 17].astype(float)                                    # total VMT, millions
DEN = pd.DataFrame({"residents": pop.POPESTIMATE2023, "drivers": drivers, "vehicles": vehicles, "vmt_millions": vmt})
A = pd.read_csv(zipfile.ZipFile("data/FARS2023NationalCSV.zip").open("FARS2023NationalCSV/accident.csv"), encoding="latin1",
                low_memory=False, usecols=["STATENAME", "FATALS"])
DEATHS = A.groupby("STATENAME").FATALS.sum().rename("deaths")
print(f"{len(DEN)} rows, the 50 states and DC; {DEATHS.sum():,} deaths")
51 rows, the 50 states and DC; 41,025 deaths

Example 1: one state, four rates

The District of Columbia and Wyoming sit at opposite ends of almost every exposure measure:

for st in ("District of Columbia", "Wyoming", "Mississippi"):
    r = R.loc[st]
    print(f"{st}: residents rank {int(ranks.loc[st, 'per_100k_residents'])}, drivers {int(ranks.loc[st, 'per_100k_drivers'])}, "
          f"vehicles {int(ranks.loc[st, 'per_100k_vehicles'])}, miles {int(ranks.loc[st, 'per_100m_miles'])}; "
          f"{r.vmt_millions * 1e6 / r.residents:,.0f} miles per resident")
District of Columbia: residents rank 47, drivers 50, vehicles 26, miles 26; 5,126 miles per resident
Wyoming: residents rank 2, drivers 2, vehicles 18, miles 12; 16,298 miles per resident
Mississippi: residents rank 1, drivers 1, vehicles 1, miles 1; 13,928 miles per resident

DC ranks 47th per resident and 26th per mile: its residents drive 5,126 miles a year each. Wyoming's drive 16,298, and the order reverses. Only Mississippi is first however exposure is measured.

Horizontal bar chart of registered vehicles per resident in 2023 for the six lowest and six highest states: Montana 2.08, Wyoming 1.52, South Dakota 1.51, North Dakota 1.35, Iowa 1.19 and Arkansas 1.09 at the top; Rhode Island and Massachusetts 0.75, New Jersey 0.64, the District of Columbia 0.51, New York 0.48 and Delaware 0.43 at the bottom, against a US figure of about 0.85. Horizontal bar chart of registered vehicles per resident in 2023 for the six lowest and six highest states: Montana 2.08, Wyoming 1.52, South Dakota 1.51, North Dakota 1.35, Iowa 1.19 and Arkansas 1.09 at the top; Rhode Island and Massachusetts 0.75, New Jersey 0.64, the District of Columbia 0.51, New York 0.48 and Delaware 0.43 at the bottom, against a US figure of about 0.85.
Vehicles per resident, the most variable denominator.

Exposure is opportunity for a crash

Choosing an exposure measure for a road crash rate. which denominator?What does the rate need to answer?how many people are lostResidentsUS 12.2 per 100,000how risky driving isDrivers or vehicles17.3 and 14.4 per 100,000how risky travel isVehicle milesUS 1.26 per 100MNone fits pedestrians and cyclists: their exposure is walking and cycling spatialworkflow.io
Which denominator.

Exposure is the amount of opportunity for a crash: people, drivers, vehicles or miles. A rate divides harm by exposure so that places of different sizes and habits can be compared, and the choice of exposure decides what is being compared. Deaths per resident is the public health view: it includes pedestrians, passengers and visitors' crashes, and it is high where people drive a lot. Deaths per mile driven is the road safety view: it asks how dangerous travel is, and it is high where each mile is risky. Drivers and vehicles fall in between, and both carry their own distortions, such as fleets registered in one state and driven elsewhere.

The rankings agree broadly, because some states are dangerous on every measure, and disagree exactly where travel habits differ most. That is the information: a state that is high per resident and average per mile has a mileage problem more than a road problem, and a state that is high per mile has roads that are dangerous to use. None of these denominators fits the deaths of pedestrians and cyclists, whose exposure is walking and cycling, for which there is no state-level count in these tables.

Footnotes, registrations and licensed drivers

Road crash rates and exposure: problems and fixes. exposure trapsTrapInsteadone rate called the riskshow two: Wyoming 2nd or 12thstate names joined rawstrip footnotes; Dist. of Col.per-vehicle rate trustedMontana: 2.08 vehicles perresidentyears mixedall denominators for the same yearFARS, Census and FHWA tables, 2023 spatialworkflow.io
Exposure traps.
  • Footnotes: FHWA tables mark estimated or adjusted values with footnote numbers in the state name; read them before relying on a single state.
  • Registrations: vehicles registered in one state and used in another, such as rental and commercial fleets, distort per-vehicle rates.
  • Licensed drivers: licences, not active drivers; older drivers who have stopped driving still hold them.
  • Person miles: VMT counts vehicle miles, not person miles; occupancy differs by state.
  • Years: all five sources are for 2023 here; mixing years shifts rates by the change in the denominator.

FAQ

What is the best denominator for road crash rates?

It depends on the question: residents for public health, vehicle miles for road safety, licensed drivers for driver risk; show more than one when places are compared.

Why do states rank differently on different crash rates?

Because residents of different states drive different distances and own different numbers of vehicles; rates per resident absorb those differences, rates per mile remove them.

Where can I get licensed drivers and registered vehicles by state?

From the Federal Highway Administration's Highway Statistics tables DL-22 and MV-1, published each year as Excel files.

What is a crash exposure measure?

A measure of the opportunity for crashes, such as population, drivers, vehicles or miles travelled, used as the denominator of a rate.