# Data
## Process starts with clean wa_2015 data
## Many dfs and plotting helpers constructed in makeWApursuits.R

# Check if need to rebuild clean pursuits data, otherwise load existing file

if(file.exists(here::here("Data", "Clean", "WA_pursuits.rda"))){
  lastmod.pursuit.data <- file.info(here::here("Data", "Clean", "WA_pursuits.rda"))$mtime
  lastmod.wa2015 <- file.info("~/GitHub/WA-FEWP/Data/Clean/WA_2015.rda")$mtime
  lastmod.pursuit.makefile <- file.info(here::here("Construction", "makeWApursuits.R"))$mtime

  
  if(lastmod.wa2015 > lastmod.pursuit.data | lastmod.pursuit.makefile > lastmod.pursuit.data) {
    message("Rebuilding pursuit dataset")
    source(here::here("Construction", "makeWApursuits.R"))
    
  } else {
    message("Loading existing dataset")
    load(here::here("Data", "Clean", "WA_pursuits.rda"))
  }
} else {
  message("Rebuilding pursuit dataset")
  source(here::here("Construction", "makeWApursuits.R"))
}
# Policy period comparisons ---
# Raw numbers, using date boundaries

## Pursuit vehicular fatalities (includes terminated pursuits) ----

policy.period.pvf <- fatalities.pvf %>%
  group_by(policy.period) %>%
  summarize(Subjects = sum(victim == "Subject"),
            Bystanders = sum(victim == "Bystander"),
            Passengers = sum(victim == "Passenger"),
            Officers = sum(victim == "Officer"),
            Total = n()
  ) %>%
  mutate(Period = policy.period)

pre.num.pvf <- policy.period.pvf$Total[policy.period.pvf$Period == "pre"]
HB1054.num.pvf <- policy.period.pvf$Total[policy.period.pvf$Period == "HB1054"]
SB5352.num.pvf <- policy.period.pvf$Total[policy.period.pvf$Period == "SB5352"]
I2113.num.pvf <- policy.period.pvf$Total[policy.period.pvf$Period == "I2113"]


## All pursuit fatalities (includes homicides and suicides) ----

policy.period.apf <- fatalities.apf %>%
  group_by(policy.period) %>%
  summarize(Subjects = sum(victim == "Subject"),
            Bystanders = sum(victim == "Bystander"),
            Passengers = sum(victim == "Passenger"),
            Officers = sum(victim == "Officer"),
            Total = n()
  ) %>%
  mutate(Period = policy.period)

pre.num.apf <- policy.period.apf$Total[policy.period.apf$Period == "pre"]
HB1054.num.apf <- policy.period.apf$Total[policy.period.apf$Period == "HB1054"]
SB5352.num.apf <- policy.period.apf$Total[policy.period.apf$Period == "SB5352"]
I2113.num.apf <- policy.period.apf$Total[policy.period.apf$Period == "I2113"]

Introduction

This report examines fatalities associated with vehicle pursuits by law enforcement in WA State since 2015.

Pursuits are unique among police tactics in their risk of collateral damage. Nationally, about one-third of pursuits lead to vehicular accidents, and a substantial fraction (over a third) of those injured or killed in these accidents are uninvolved bystanders, passengers and officers.

Here in Washington state, recent legislative changes provide an opportunity to observe whether pursuit policies can help to reduce these fatalities.

What this report covers

The report examines the range of fatalities that are associated with police vehicular pursuits:

  • “Pursuit vehicular fatalities” - an active or recently terminated vehicular pursuit led to a vehicular homicide caused by one of the cars involved in the pursuit.

  • “After pursuit fatalities” – a pursuit was involved earlier in the incident, but had ended by the time the fatality occurred. Typically the person killed in these cases is the fleeing subject who is shot by police at the end of the chase.

  • “Attempted stop fatalities” – a subject fled an attempted stop by police and committed a vehicular homicide in the process, but the police vehicle did not engage in pursuit.

The majority of the report focuses on the first two types: pursuit vehicular fatalities and after pursuit fatalities, examined separately. The attempted stop fatalities are different for several reasons, so we address them in a section of their own.

How the report is organized

The table of contents on the left shows the outline of the information. All of the entries are linked and can be used to navigate through the report. Note that clicking on an entry of the TOC will cause the sub-headings to display if there are any.

Within each section of the report listed in the TOC, you may find “tabs” on the page that contain additional information. The active tab is highlighted with a blue filled box, and you can click the inactive tabs on either side of the active tab to access their information.

The graphics use a consistent color coding to help with comparisons, and the color scheme is linked to the type of data in the graph: pursuit vehicular fatalities (color codes for victim type), after pursuit fatalities (color codes for homicide vs. suicide), and incidents (color codes for pursuit vehicular fatalities and after pursuit fatalities).

Legislative history

Pursuit policy has been an active area of legislation in WA State, with parallels to the policy changes that took place in Milwaukee, WI. The changes define four policy periods in WA state useful for comparative analysis:

Pre-reform

before July 25, 2021

Pursuit policies during this period were decentralized, and established by each agency, so there was a patchwork of different policies across the state. Some policies were quite restrictive, others left decisions to the discretion of officers. In this report, we look back to Jan 1, 2015 as the start of this observation period.

HB1054

July 25, 2021 - May 2, 2023

In 2021 the legislature enacted a statewide policy to provide a uniform standard and to improve public safety by reducing the growing number of people killed during these pursuits (House Bill 1054, effective July 25, 2021). At the time, pursuits were responsible for 10-20% of the fatalities from police activities each year. About half of those killed were passengers, officers or uninvolved bystanders.

HB 1054 established a clear standard for balancing the danger posed to the public by the pursuit against the danger posed by a fleeing subject. It prioritized public safety: police are allowed to engage in pursuits when there is a well established threat to public safety – violent offenses (like carjackings, armed robberies), sex offenses, DUIs, and prison escapes – but not for misdemeanors or property crimes. It required that the evidence of the threat meets the “probable cause” standard – the same standard required to make an arrest. In effect the law said: If you don’t have enough evidence to arrest the person, then you can not justify the risk to public safety for this pursuit.

SB5253

May 3, 2023 - June 5, 2024

In 2023 the legislature modified the policy, lowering the standard of evidence required from probable cause to reasonable suspicion, adding vehicular and domestic assaults explicitly to the list of offenses eligible for pursuit, and removing the requirement for supervisory authorization. These changes took effect May 3, 2023.

I2113

after June 5, 2024 (Current)

In response to a successful initiative campaign to place a pursuit policy rollback on the November 2024 ballot, the legislature took the option of passing the initiative themselves in March 2024. The initiative removed all of the explicit public safety requirements for allowable pursuits, and replaced them with a simple discretionary requirement that “the threat to the safety of others and the safety risks of failing to apprehend or identify the person are considered to be greater than the safety risks of the vehicular pursuit under the circumstances.”

The full texts of the bills passed and the current law (RCW) on vehicle pursuits can be found in the Pursuit legislation section at the end of this report.

Impact of policy changes

There are now 4 different policy periods observed in the decade of data we are tracking. We compare them below using an estimated annualized rate of pursuit-related fatalities for each period.

annual_rate_df <- fatalities.pvf %>%
  group_by(year, month) %>%
  summarize(num.fatalities = n(),
            policy.period.incident = first(policy.period)) %>%
  left_join(index.monthly, .,
            by = join_by("year"=="year", "mon"=="month")) %>%
  mutate(policy.period = case_when(
    index.date < date.HB1054 ~ "pre-reform",
    (index.date >= date.HB1054 & index.date < date.SB5352) ~ "HB1054",
    (index.date >= date.SB5352 & index.date < date.I2113) ~ "SB5352",
    index.date >= date.I2113 ~ "I2113"),
    
    "Policy period" = factor(policy.period, 
                           levels = c("pre-reform", "HB1054", "SB5352", "I2113"))
  ) %>%
  
  group_by(`Policy period`) %>%
  summarize(
    Fatalities = sum(num.fatalities, na.rm=T)
  ) %>%
  mutate(Years = case_when(
    `Policy period` == "pre-reform" ~ round(yrs.pre, 1),
    `Policy period` == "HB1054" ~ round(yrs.HB1054, 1),
    `Policy period` == "SB5352" ~ round(yrs.SB5352, 1),
    `Policy period` == "I2113" ~ round(yrs.I2113, 1)
    )
  ) %>%
  mutate("Annualized rate" = round(Fatalities/Years, 1)) 

ann_rate_HB1054 <- annual_rate_df$`Annualized rate`[annual_rate_df$`Policy period` == "HB1054"]

annual_rate_df <- annual_rate_df %>%
  mutate(`Rate relative to HB1054` = round(`Annualized rate`/ann_rate_HB1054, 1))

fatality_change <- round(annual_rate_df$`Annualized rate`[annual_rate_df$`Policy period` == "I2113"] - 
  annual_rate_df$`Annualized rate`[annual_rate_df$`Policy period` == "HB1054"], 0)

Graph

ymax <- max(annual_rate_df$`Annualized rate`)

xbrks <- levels(annual_rate_df$`Policy period`)
xlabs <- c(
  paste0(
    "Pre-reform \n",
    format(date.start, "%m/%d/%y"), " - ",
    format(date.HB1054 - 1, "%m/%d/%y"), "\n",
    round(yrs.pre,1), " yrs"),
  paste0(
    "HB1054 \n",
    format(date.HB1054, "%m/%d/%y"), " - ",
    format(date.SB5352 - 1, "%m/%d/%y"), "\n",
    round(yrs.HB1054,1), " yrs"),
  paste0(
    "SB5352 \n",
    format(date.SB5352, "%m/%d/%y"), " - ",
    format(date.I2113 - 1, "%m/%d/%y"), "\n",
    round(yrs.SB5352,1), " yrs"),
  paste0(
    "I2113 \n",
    "Current \n",
    round(yrs.I2113,1), " yrs")
)

p <- ggplot(annual_rate_df, 
            aes(x=`Policy period`, y=`Annualized rate`, 
                fill=`Annualized rate`)) +
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +
  

  labs(title = "Annualized pursuit fatality rates by policy period",
       x = "Policy Period",
       y = "Annual fatality rate from pursuits") +
  
  scale_fill_gradient(low = "seashell", high = "firebrick",
                      guide = "none") +
  
  scale_y_continuous(breaks = 0:(ymax + 2))  +
  scale_x_discrete(breaks=xbrks, labels=xlabs)


ggplotly(p)

In the short time since I-2113 rolled back the pursuit safety restrictions, the data show that the pursuit-related fatality rate has risen dramatically.

  • It is now 6.1 times as high as it was during the HB1054 period, when pursuits were restricted to violent felonies and DUIs.

  • In a typical year, this means 14 more people will be killed as a result of police pursuits.

While the exact value of the policy effects will depend on the metric used, the pattern observed in the data is clear:


The WA statewide pursuit safeguards adopted in 2021 were working as intended to improve public safety: they were saving lives. The cost of weaking those safeguards has been a sharp rise in pursuit-related fatalities.


The pattern here in WA mirrors what happened in Milwaukee, WI before, during and after the 5 years that their policy restricted pursuits to violent offenses (see the official City of Milwaukee pursuit reports here).


Table

annual_rate_df %>%
 
  kbl(caption = "Annualized pursuit fatality rates by policy period*",
      align = "lrrrr") %>%
  kable_styling(bootstrap_options = "striped") %>%
  add_footnote("Includes fatalities from active and recently terminated pursuits only.",
               notation = "symbol")
Annualized pursuit fatality rates by policy period*
Policy period Fatalities Years Annualized rate Rate relative to HB1054
pre-reform 25 6.6 3.8 1.4
HB1054 5 1.8 2.8 1.0
SB5352 8 1.1 7.3 2.6
I2113 24 1.4 17.1 6.1
* Includes fatalities from active and recently terminated pursuits only.

Comments

There are different methods one can use to assess the impacts of the sequence of pursuit policy changes in WA. But it is complicated by the fact that the lengths of the policy periods are quite different, the dates the policies became effective do not line up with any type of standardized year (calendar or legislative), and the fatality counts for the shorter policy periods are too small to support a robust statistical analysis. We previously reported a fatality count comparison with a standardized time window, pre and post reform. But with 4, different length, policy periods, that approach no longer works.

For this policy impact summary section we have decided to report annualized fatality rates for each policy period. This metric has both benefits and drawbacks:

  • Benefits – It provides a single summary number that can be compared across all periods, regardless of their length, and it allows us to use the exact dates when legislation became effective to define the periods.

  • Drawbacks – In contrast to the number of persons killed in a specific legislative year (or other standardized time frame), the annualized fatality rate is an estimate of the average rate of fatalities per year. The reliability of that estimate depends on the number of years observed. In our case the policies changed so frequently that several periods are quite short, which means the annualized estimate we get is not very reliable.

In later sections of this report we present fatalities broken down by calender and approximate legislative year, showing the breakdown of the victims (officer, bystanders, passengers, subjects) in each timeframe.


Interactive Maps

The first map is restricted to pursuit vehicular fatalities only.

The second map adds in after pursuit fatalities.

Pursuit vehicular fatalities

Each marker represents an active vehicle pursuit that ended with a vehicular homicide.

  • Red markers are pursuits that resulted in bystanders, passengers and/or officers (B/P/O) being killed or injured.

  • Blue markers are pursuits with subject fatalities only

  • The icon inside the marker shows whether this was a single or multiple fatality incident.

This map is also interactive:

  • Hovering over the pointer brings up the number of people killed and injured, the law enforcement agency involved, and the date of the incident;

  • Clicking the pointer will bring up a url to a news article on the incident.

# Make icons for single/multiple fatality incidents

# color = incident type for map:
## red = ap with any pb killed, 
## blue = ap with subject killed, 
# icon = number killed (single/multiple)

iconset <- awesomeIconList(
  single = makeAwesomeIcon(
    icon = 'user',
    library = 'fa',
    iconColor = 'white',
    markerColor = ~ inci.mapcolor
  ),
  mult = makeAwesomeIcon(
    icon = 'users',
    library = 'fa',
    iconColor = 'white',
    markerColor = ~ inci.mapcolor
  ))

iconset.legend <- awesomeIconList(
  `B/P/O killed` = makeAwesomeIcon(
    icon = 'user',
    library = 'fa',
    iconColor = 'black',
    markerColor = 'red',
  ),
  `Subject killed` = makeAwesomeIcon(
    icon = 'user',
    library = 'fa',
    iconColor = 'black',
    markerColor = 'blue',
  ),
  `Multiple fatalities` = makeAwesomeIcon(
    icon = 'users',
    library = 'fa',
    iconColor = 'black',
    markerColor = 'white',
  ))

labs <- with(incidents.pvf, 
              as.character(paste("fatalities:", 
                                 fatalities, '<br>',
                                 "injuries:",
                                 total.injuries, '<br>',
                                 'by', agency, '<br>',
                                 'date: ', format(date, format="%m/%d/%y"))))

map <- leaflet(
  data = incidents.pvf, 
  width = "100%") %>% 
  addTiles() %>%
  
  addAwesomeMarkers( ~ long, ~ lat,
                    popup = ~ url_click,
                    label = lapply(labs, htmltools::HTML),
                    icon = ~iconset[inci.mapmult]) %>%
  
  addLegendAwesomeIcon(iconSet = iconset.legend,
                       orientation = 'vertical',
                       title = htmltools::tags$div(
                         style = 'font-size: 10px;',
                         'Incident type'),
                       labelStyle = 'font-size: 8px;') %>%
  
  leaflet.extras::addResetMapButton()
map

Pursuit Statistics

Pursuit statistics can be counted in two ways:

  • Number of people killed (“fatalities”)

  • Number of incidents

Since more than one person may be killed in an incident the number of incidents will generally be smaller than the number of people killed. Fatalities are a better metric for understanding who is at risk from pursuits. Incidents are a better metric for understanding the agencies involved. We look at both below.

People killed

Summary

How often are pursuits involved?


Pursuits are involved in 29% of fatal encounters with police.


The table below breaks down all fatalities from police activities in WA since 2015 – noting if and how a pursuit was involved. The categories are:

  • Vehicle not involved – No indication that a vehicle-related fatality was involved in the incident that led to this fatality.

  • Pursuit vehicular fatality – A pursuit led directly to a vehicular fatality (e.g., a crash or someone getting run over). This includes active and recently terminated pursuits (see Coding section for more details)

  • After pursuit fatality – A vehicle pursuit occurred during the incident, but was not the immediate cause of the fatality. Most of these cases are gun-related fatalities (79% are either shot by police or die of a self-inflicted gunshot, the homicides and suicides are reported separately in the table below) the rest are fatalities from vehicle accidents.

  • Attempted stop – The subject fled a traffic stop and a vehicular fatality resulted, but police report they did not engage in pursuit.

  • Vehicle accident – An officer commits a vehicular homicide (on- or off-duty), but there is no pursuit involved.

fatalities.all %>%
  mutate(`Incident category` = case_when(
    grepl("Not", pursuit.type) ~ "Vehicle not involved",
    grepl("Involved", pursuit.type) ~ "After pursuit fatality",
    grepl("pursuit", pursuit.type) ~ "Pursuit vehicular fatality",
    grepl("stop", pursuit.type) ~ "Attempted stop fatality",
    TRUE ~ "Vehicle accident fatality (non-pursuit)")
  ) %>% 
  count(`Incident category`) %>%
  arrange(desc(n)) %>%
  mutate(Percent = round(100*n/sum(n), 1)) %>%
  rename(Number = n) %>%

  kbl(caption = "Pursuit involvement in fatal police encounters",
      align = "lrr") %>%
  pack_rows("Pursuit related", 2,3) %>%
  pack_rows("Other vehicle related", 4,5) %>%
  kable_styling(bootstrap_options = "striped") %>%
  row_spec(1, bold=T) %>%

  add_footnote("Data include all fatalities during a police encounter in WA since 2015.",
               notation = "symbol")
Pursuit involvement in fatal police encounters
Incident category Number Percent
Vehicle not involved 328 66.0
Pursuit related
After pursuit fatality 82 16.5
Pursuit vehicular fatality 62 12.5
Other vehicle related
Attempted stop fatality 17 3.4
Vehicle accident fatality (non-pursuit) 8 1.6
* Data include all fatalities during a police encounter in WA since 2015.

Who gets killed?


53% of the persons killed during pursuits since 2015 in WA have been passengers, officers or uninvolved bystanders.


tab <- fatalities.pvf %>%
  group_by(Victim=victim) %>%
  summarize(Number = n()) %>%
  mutate(Percent = Number/sum(Number)) %>%
  arrange(desc(Number)) %>%
  bind_rows(data.frame(Victim ="Total",
                       Number = sum(.$Number),
                       Percent = sum(.$Percent))) %>%
  mutate(Percent = scales::percent(Percent),
        Victim = factor(Victim, 
                         levels = c("Subject", "Bystander", "Passenger",
                                    "Officer", "Total"))) 

tab %>%
  arrange(Victim) %>%
  
  kbl(caption = "Victims of vehicular pursuits in WA since 2015",
      digits = c(0,0,1),
      align = "lrr") %>%
  kable_styling(bootstrap_options = "striped") %>%
  row_spec(which(tab$Victim == "Total"), bold=T) %>%
  
  footnote("See Data section for information on data sources and coding.")
Victims of vehicular pursuits in WA since 2015
Victim Number Percent
Subject 29 46.8%
Bystander 14 22.6%
Passenger 17 27.4%
Officer 2 3.2%
Total 62 100.0%
Note:
See Data section for information on data sources and coding.

Trend over time

There are several ways we can examine the data over time. Some are better suited to revealing the impact of the policy change than others.

  • Policy period: This is a simple count of fatalities in each period, so is easy to understand and plot, but because the periods represent different lengths of time, direct comparisons are misleading.

  • Calendar year: This is a common way to aggregate the fatality counts into standardized time units in a single graphic, but it does not give a clear picture of the policy impacts because the laws changed in the middle of 2021, the middle of 2023, and the middle of 2024.

  • Legislative year: Aggregating the fatality counts into standardized legislative years does a somewhat better job of showing the policy impacts, but is still not accurate because the standardized years don’t perfectly line up with when legislation becomes effective.

For both Calendar and Legislative year plots, the current year shows the year to date (YTD) count, so it is not strictly comparable to previous years. The YTD count may rise by the end of the year but it will not decline. As a result increases from previous years to the current YTD are meaningful but potentially under-estimate the difference, while declines observed from previous years to the current YTD are not meaningful since this year’s total is not complete.

Policy period

The key changes to statewide pursuit law went into effect July 25, 2021 (HB1054, the original statewide policy with the strongest public safeguards), May 03, 2023 (SB5352, the bill that lowered the threshold from probable cause to reasonable suspicion) and June 05, 2024 (I2113, the bill that removed explicit guidelines and replaced them with officer discretion). This divides our observation period into four parts.


The lengths of the periods are quite different, so direct comparisons of the counts are misleading.


Pursuit vehicular fatalities

The plot below displays the number of people killed in each period, broken down by the status of the victim.

  • Hovering over the bars will bring up number of persons killed for each segment of the bar.
df <- fatalities.pvf %>%
  group_by(policy.period, Victim=victim) %>%
  summarize(Number = n()) %>%
  group_by("Policy period" = policy.period) %>%
  mutate(Total = sum(Number))

ymax <- max(df$Total)

xbrks <- levels(df$`Policy period`)
xlabs <- c(
  paste0(
    "Pre-reform \n",
    format(date.start, "%m/%d/%y"), " - ",
    format(date.HB1054 - 1, "%m/%d/%y"), "\n",
    round(yrs.pre,1), " yrs"),
  paste0(
    "HB1054 \n",
    format(date.HB1054, "%m/%d/%y"), " - ",
    format(date.SB5352 - 1, "%m/%d/%y"), "\n",
    round(yrs.HB1054,1), " yrs"),
  paste0(
    "SB5352 \n",
    format(date.SB5352, "%m/%d/%y"), " - ",
    format(date.I2113 - 1, "%m/%d/%y"), "\n",
    round(yrs.SB5352,1), " yrs"),
  paste0(
    "I2113 \n",
    "Current \n",
    round(yrs.I2113,1), " yrs")
)


p <- ggplot(df, aes(x=policy.period, y=Number, 
                    fill = Victim)) +
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +
  
  labs(title = "Pursuit vehicular fatalities by policy period (non-comparable period lengths)",
       x = "Policy Period",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4) +
  
  scale_y_continuous(breaks = seq(0, ymax + 2, 2))  +
  scale_x_discrete(breaks=xbrks, labels=xlabs)

  

ggplotly(p) #%>% reverse_legend_labels()

After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

  • Hovering over the bars will bring up number of persons killed for each bar segment.
df <- fatalities.apf %>%
  group_by(incident.type, policy.period) %>%
  summarize(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(policy.period) %>%
  mutate(Total = sum(Number))

p <- ggplot(df, aes(x=policy.period, y=Number, 
                    fill = Fatality)) +
  
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +
  
  # annotate("text",
  #          x = length(unique(df$policy.period)),
  #          y = df$Total[nrow(df)] + 1,
  #          label = "Period to date", size = 3) +
  
  labs(title = "After pursuit fatalities by policy period (non-comparable period lengths)",
       x = "Policy period",
       y = "Number")  +

  scale_y_continuous(breaks = seq(0, (max(df$Total) + 2), 5))   +
  scale_x_discrete(breaks=xbrks, labels=xlabs) +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))


ggplotly(p) #%>% reverse_legend_labels()

Calendar year

This is a common way to aggregate the fatality counts into standardized time units, but it does not give a clear picture of the policy impacts because the laws changed in the middle of 2021, 2023 and 2024.

Note that the current year shows the count for the year to date (YTD) – January 1 - November 11, 2025 – so it is not strictly comparable to the other years. The YTD count may rise, but it will not decline. As a result increases from previous years to the current YTD are meaningful but potentially under-estimate the difference, while declines observed from previous years to the current YTD are not meaningful since this year’s total is not complete.

Pursuit vehicular fatalities

The plot below displays the number of people killed in each calendar year, broken down by the status of the victim.

  • Hovering over the bars will bring up number of persons killed for each bar segment.
df <- fatalities.pvf %>%
  group_by(Year=year, Victim=victim) %>%
  summarize(Number = n()) %>%
  left_join(allrows.calyr.pvf, .) %>%
  mutate(Number = tidyr::replace_na(Number,0)) %>%
  group_by(Year) %>%
  mutate(Total = sum(Number))

ymax <- max(df$Total)

p <- ggplot(df, aes(x=Year, y=Number, 
                    fill = Victim)) +
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +
  
  annotate("text",
           x = max.yr,
           y = df$Total[nrow(df)] + 0.5,
           label = "YTD", size = 3) +
  
  labs(title = "Pursuit vehicular fatalities by calendar year",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4) +
  
  ylim(0, (ymax + 2)) +
  scale_y_continuous(breaks = 1:(ymax + 2)) +
  scale_x_continuous(breaks = min.yr:max.yr)

  
ggplotly(p) #%>% reverse_legend_labels()

After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

  • Hovering over the bars will bring up number of persons killed for each bar segment.
df <- fatalities.apf %>%
  group_by(incident.type, Year=year) %>%
  summarize(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(Year) %>%
  mutate(Total = sum(Number))

p <- ggplot(df, aes(x=Year, y=Number, 
                    fill = Fatality)) +
  
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +
  
  annotate("text",
           x = max.yr,
           y = df$Total[nrow(df)] + 0.5,
           label = "YTD", size = 3) +
  
  labs(title = "After pursuit fatalities by calendar year",
       y = "Number") +
  
  scale_x_continuous(breaks = min.yr:max.yr) +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))
  
  
ggplotly(p) #%>% reverse_legend_labels()

Legislative year

Aggregating the fatality counts into standardized legislative years does a better job of showing the policy impacts, but because the standardized years don’t exactly line up with when legislation becomes effective the timing is still a bit inacurate.

Note that the current legislative year is year to date – August 1 - November 11, 2025– so it is not strictly comparable to the other years. The YTD count may rise but it will not decline. As a result increases from previous years to the current YTD are meaningful but potentially under-estimate the difference, while declines observed from previous years to the current YTD are not meaningful since this year’s total is not complete.

We exclude data from the 2014-2015 legislative year since our data observation period starts in January 2015 which does not cover that whole legislative year.

Pursuit vehicular fatalities

The plot below displays the number of people killed in each legislative year, broken down by the status of the victim.

  • Hovering over the bars will bring up the number of persons killed.
df <- fatalities.pvf %>%
  filter(date > as.Date("2015-07-30")) %>% # to get the first complete year
  group_by(leg.year, Victim=victim) %>%
  summarize(Number = n()) %>%
  left_join(allrows.legyr.pvf, .) %>%
  mutate(Number = tidyr::replace_na(Number,0)) %>%
  group_by(leg.year) %>%
  mutate(Total = sum(Number),
         leg.year = gsub("Aug|Jul", "", leg.year))
 
ymax <- max(df$Total)
hb1054 <- max(which(df$leg.year == "2020-2021"))/4
sb5352 <- max(which(df$leg.year == "2022-2023"))/4
i2113 <- max(which(df$leg.year == "2023-2024"))/4

p <- ggplot(df, 
            aes(x=leg.year, y=Number,
                fill=Victim)) +
  
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +

  # policy period separators
  
  geom_vline(xintercept =  hb1054 + .5, color="grey") + 
  geom_vline(xintercept =  sb5352 + .5, color="grey") + 
  geom_vline(xintercept =  i2113 + .5, color="grey") + 
  
  annotate("text", 
           x = "2017-2018", 
           y = ymax + 1.5, 
           label = "Pre-reform", size = 3) +
  
  annotate("text", 
           x = "2021-2022", 
           y = ymax + 1.5, 
           label = "HB1054", size = 3) +
  
    annotate("text", 
           x = "2023-2024", 
           y = ymax + 1.5, 
           label = "SB5253", size = 3) +
  
  annotate("text", 
           x = "2024-2025", 
           y = ymax + 1.5, 
           label = "I2113", size = 3) +
  
  annotate("text",
           x = max(df$leg.year), # is a factor
           y = df$Total[nrow(df)] + 0.5,
           label = "LYTD", size = 3) +
  
  labs(title = "Pursuit vehicular fatalities by legislative year",
       x = "Legislative Year",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4) +

  scale_y_continuous(limits = c(0, ymax+2),
                     breaks= 1:(ymax + 1)) +
  

  
  theme(axis.text.x = element_text(size = rel(0.7)))

  
ggplotly(p) #%>% reverse_legend_labels() 
After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, with the number of each is shown in the bars. Most of these deaths are caused by gunshot.

  • Hovering over the bars will bring up number of persons killed for each bar segment.
df <- fatalities.apf %>%
  filter(date > as.Date("2015-07-30")) %>% # to get the first complete year
  group_by(incident.type, leg.year) %>%
  summarize(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(leg.year) %>%
  mutate(Total = sum(Number),
         leg.year = gsub("Aug|Jul", "", leg.year))

ymax <- max(df$Total)
hb1054 <- max(which(df$leg.year == "2020-2021"))/2 - 1
sb5352 <- max(which(df$leg.year == "2022-2023"))/2
i2113 <- max(which(df$leg.year == "2023-2024"))/2 + .5

p <- ggplot(df, 
            aes(x=leg.year, y=Number,
                fill=Fatality)) +
  
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +

  # policy period separators
  
  geom_vline(xintercept =  hb1054 + .5, color="grey") + 
  geom_vline(xintercept =  sb5352 + .5, color="grey") + 
  geom_vline(xintercept =  i2113 + .5, color="grey") + 
  
  annotate("text", 
           x = "2017-2018", 
           y = ymax + 1.5, 
           label = "Pre-reform", size = 3) +
  
  annotate("text", 
           x = "2021-2022", 
           y = ymax + 1.5, 
           label = "HB1054", size = 3) +
  
    annotate("text", 
           x = "2023-2024", 
           y = ymax + 1.5, 
           label = "SB5253", size = 3) +
  
  annotate("text", 
           x = "2024-2025", 
           y = ymax + 1.5, 
           label = "I2113", size = 3) +
  
  annotate("text",
           x = max(df$leg.year), # is a factor
           y = df$Total[nrow(df)] + 0.5,
           label = "LYTD", size = 3) +
  
  labs(title = "After pursuit fatalities by legislative year",
       x = "Legislative Year",
       y = "Number") +
  
  
  scale_y_continuous(limits = c(0, ymax+2),
                     breaks= 1:(ymax + 2)) +
  
  scale_fill_manual(values = c("gold2", "steelblue4")) +


  theme(axis.text.x = element_text(size = rel(0.7)))
  
ggplotly(p) %>% reverse_legend_labels() 

Agencies

Agencies introduce another counting metric, since multiple agencies may be involved in a single incident.

In this section we identify every agency involved in at least one pursuit-related fatality, along with the number and type of fatalities from the incidents involved (“Each agency count”). This means that fatalities will be multiply counted for incidents with multiple agency involvement, and the totals cannot be compared to those in previous sections. For cross-reference, we also include a graph with the multi-agency fatalities grouped together (“Multi-agency count”).

By type

Pursuit vehicular fatalities
Each agency count
df <- agency.fatality.p.long  %>%
  filter(grepl("vehicular", incident.type)) %>%
  group_by(agency.type, Victim=victim) %>%
  summarise(Number = n()) %>%
  group_by(agency.type) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.pvf)) # percent of fatalities, sum > 100

 
p <- ggplot(df, 
            aes(x = reorder(agency.type, Total), y = Number, 
                fill = Victim,
                text = paste("Victim: ", Victim, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 1) +
  
  labs(title = "Pursuit Vehicular Fatalities by Agency Type: Each agency count*",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "Agency type",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4)

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Fatalities are counted more than once if multiple agencies are involved.

Multi-agency count
df <- fatalities.pvf  %>%
  group_by(agency.type, Victim=victim) %>%
  summarise(Number = n()) %>%
  group_by(agency.type) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.pvf))

 
p <- ggplot(df, 
            aes(x = reorder(agency.type, Total), y = Number, 
                fill = Victim,
                text = paste("Victim: ", Victim, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 1) +
  
  labs(title = "Pursuit Vehicular Fatalities by Agency Type: Multi-agency count*",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "Agency type",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4)

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Each fatality only counts once

After pursuit fatalities

These graphs show only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

Each agency count
df <- agency.fatality.p.long  %>%
  filter(!grepl("vehicular", incident.type)) %>%
  group_by(agency.type, incident.type) %>%
  summarise(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(agency.type) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.apf))
 
p <- ggplot(df, 
            aes(x = reorder(agency.type, Number), y = Number, 
                fill = Fatality,
                text = paste("Type: ", Fatality, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 1) +
  
  labs(title = "After Pursuit Fatalities by Agency Type: Each agency count*",
       caption = "WA State since 2015",
       x = "Agency type",
       y = "Number") +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Fatalities are counted more than once if multiple agencies are involved.

Multi-agency count
df <- fatalities.apf  %>%
  group_by(agency.type, incident.type) %>%
  summarise(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(agency.type) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.apf))
 
p <- ggplot(df, 
            aes(x = reorder(agency.type, Number), y = Number, 
                fill = Fatality,
                text = paste("Type: ", Fatality, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 1) +
  
  labs(title = "After Pursuit Fatalities by Agency Type: Multi-agency count*",
       caption = "WA State since 2015",
       x = "Agency type",
       y = "Number") +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Each fatality only counts once

By name

For these graphs, we report only the “each agency count” statistics.

Pursuit vehicular fatalities

The plot below displays the number of people killed in each period, broken down by the status of the victim.

df <- agency.fatality.p.long  %>%
  filter(grepl("vehicular", incident.type)) %>%
  
  mutate(agency = gsub("Washington", "WA", agency),
         agency = gsub("County Sheriff's Office", "Co SO", agency),
         agency = gsub("Police Department", "PD", agency),
         agency = ifelse(grepl(",", agency), "Multiple agencies", agency)) %>%
  group_by(agency, Victim=victim) %>%
  summarise(Number = n()) %>%
  group_by(agency) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.pvf))
 
p <- ggplot(df, 
            aes(x = reorder(agency, Total), y = Number,
                fill = Victim,
                text = paste("Victim: ", Victim, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "Pursuit Vehicular Fatalities by Agency: Each agency count*",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "Agency",
       y = "Number") +

  scale_fill_manual(values = cols.pvf.4) +
  scale_y_continuous(breaks = 0:max(df$Total)) +
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Fatalities are counted more than once if multiple agencies are involved.

After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

df <- agency.fatality.p.long  %>%
  filter(!grepl("vehicular", incident.type)) %>%
  
    mutate(agency = gsub("Washington", "WA", agency),
           agency = gsub("County Sheriff's Office", "Co SO", agency),
           agency = gsub("Police Department", "PD", agency),
           agency = ifelse(grepl(",", agency), "Multiple agencies", agency)) %>%
  group_by(agency, incident.type) %>%
  summarise(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(agency) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.apf))
 
p <- ggplot(df, 
            aes(x = reorder(agency, Total), y = Number, 
                fill = Fatality,
                text = paste("Type: ", Fatality, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "After Pursuit Fatalities by Agency: Each agency count*",
       caption = "WA State since 2015",
       x = "Agency",
       y = "Number") +
  
  scale_fill_manual(values = c("gold2", "steelblue4")) +
  scale_y_continuous(breaks = 0:(max(df$Total)+1), 
                     labels = as.character(0:(max(df$Total)+1))) +
  theme(axis.text.y=element_text(size=6)) +
  
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Fatalities are counted more than once if multiple agencies are involved.

Geography

By County

Pursuit vehicular fatalities

The plot below displays the number of people killed in each period, broken down by the status of the victim.

df <- fatalities.pvf  %>%
  group_by(County=county, Victim=victim) %>%
  summarise(Number = n()) %>%
  group_by(County) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.pvf))
 
p <- ggplot(df, 
            aes(x = reorder(County, Total), y = Number, 
                fill = Victim,
                text = paste("Victim: ", Victim, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "Pursuit Vehicular Fatalities by County",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "County",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4) +
  scale_y_continuous(breaks = 0:max(df$Total))+
  coord_flip()  

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

df <- fatalities.apf  %>%
  group_by(County=county, incident.type) %>%
  summarise(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(County) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.apf))
 
p <- ggplot(df, 
            aes(x = reorder(County, Total), y = Number, 
                fill = Fatality,
                text = paste("Type: ", Fatality, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "After Pursuit Fatalities by County",
       caption = "WA State since 2015",
       x = "County",
       y = "Number") +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))+
  scale_y_continuous(breaks = 0:max(df$Total))+
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

By City

Pursuit vehicular fatalities

The plot below displays the number of people killed in each period, broken down by the status of the victim.

df <- fatalities.pvf  %>%
  group_by(City=city, Victim=victim) %>%
  summarise(Number = n()) %>%
  group_by(City) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.pvf))
 
p <- ggplot(df, 
            aes(x = reorder(City, Total), y = Number, 
                fill = Victim,
                text = paste("Victim: ", Victim, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "Pursuit Vehicular Fatalities by City",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "City",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4) +
  scale_y_continuous(breaks = 0:max(df$Total))+
  coord_flip()  

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

There are too many cities to be legible if plotted, so we restrict the cities to those with 2 or more after pursuit fatalities.

df <- fatalities.apf  %>%
  rename(City=city) %>%
  group_by(City, incident.type) %>%
  summarise(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide")))  %>%
  group_by(City) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.apf)) %>%
  filter(Total >= 2)

incl.pct <- sum(df$Percent)

p <- ggplot(df, 
            aes(x = reorder(City, Total), y = Number, 
                fill = Fatality,
                text = paste("Type: ", Fatality, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.3) +
  
  labs(title = paste("After Pursuit Fatalities by City: Cities with 2+ only, incl.", 
                     scales::percent(incl.pct, acc=1), "of incidents"),
       caption = "WA State since 2015",
       x = "City",
       y = "Number") +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))+
  scale_y_continuous(breaks = 0:max(df$Total))+
  theme(axis.text.y = element_text(size = rel(0.9))) +
  
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

By Legislative District

Pursuit vehicular fatalities

The plot below displays the number of people killed in each period, broken down by the status of the victim.

df <- fatalities.pvf  %>%
  filter(!is.na(WA_District)) %>%
  group_by(WA_District, Victim=victim) %>%
  summarise(Number = n()) %>%
  group_by(WA_District) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.pvf))
 
p <- ggplot(df, 
            aes(x = reorder(WA_District, Total), y = Number, 
                fill = Victim,
                text = paste("Victim: ", Victim, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "Pursuit Vehicular Fatalities by WA Legislative District",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "District",
       y = "Number") +
  
  scale_fill_manual(values = cols.pvf.4) +
  scale_y_continuous(breaks = 0:max(df$Total))+
  coord_flip()  

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

After pursuit fatalities

This graph shows only the “after pursuit” fatalities: incidents where there has been a pursuit, but the death occurs after the pursuit ended. These include both homicides and suicides following a pursuit, and the number of each is shown in the bars. Most of these deaths are caused by gunshot.

df <- fatalities.apf  %>%
  filter(!is.na(WA_District)) %>%
  group_by(WA_District, incident.type) %>%
  summarise(Number = n()) %>%
  mutate(Fatality = factor(ifelse(grepl("suicide", incident.type), "Suicide", "Homicide"),
                           levels = c("Suicide", "Homicide"))) %>%
  group_by(WA_District) %>%
  mutate(Total = sum(Number))  %>%
  mutate(Percent = Total/nrow(fatalities.apf))
 
p <- ggplot(df, 
            aes(x = reorder(WA_District, Total), y = Number, 
                fill = Fatality,
                text = paste("Type: ", Fatality, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
            size = 3, nudge_y = 0.5) +
  
  labs(title = "After Pursuit Fatalities by 2023 WA Legislative District",
       caption = "WA State since 2015",
       x = "District",
       y = "Number") +
  
  scale_fill_manual(values = c("gold2", "steelblue4"))+
  scale_y_continuous(breaks = 0:max(df$Total))+
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

WA 2025 LD map

The current legislative district map can be found on the WA leg.gov website.

The map for 2025 shown below is taken from this WA leg.gov website

knitr::include_graphics(here::here("Images", "WALD2025.PNG"))

____

Incident characteristics

These tables and graphs break down the number of incidents, rather than persons killed, and we restrict the focus to incidents with active pursuit fatalities. In active pursuit incidents more than one person may be killed, so there are fewer incidents than fatalities. The same is not true for the after pursuit fatalities in our dataset: each of these only has one fatality. So an “incident-based” analysis is the same as a “fatality-based” analysis for those incidents, and the results would be the same as in the previous section.

Recall that we do not have data on all vehicular pursuit incidents – we only have data on the incidents that result in a fatality.

Fatalities per incident

We only observe multi-fatality incidents for the pursuit vehicular homicides. There may have been accidents and injuries during the after pursuit fatalities but we are not capturing those in our data.

incidents.pvf  %>%
  group_by(Fatalities=fatalities) %>%
  summarize(Number = n()) %>%
  mutate(Percent = Number/sum(Number),
         Fatalities = as.character(Fatalities)) %>%
  bind_rows(data.frame(Fatalities = "Total",
                       Number = sum(.$Number),
                       Percent = sum(.$Percent))) %>%
  mutate(Percent = scales::percent(Percent)) %>%
  
  kbl(caption = "Pursuit vehicular fatalities per incident*",
      align = "lrr",
      digits = c(0,0,1)) %>%
  kable_styling(bootstrap_options = "striped") %>%
  row_spec(4, bold = T) %>%
  add_footnote("Incidents with pursuit fatalities in WA since 2015", notation = "symbol")
Pursuit vehicular fatalities per incident*
Fatalities Number Percent
1 49 89.1%
2 5 9.1%
3 1 1.8%
Total 55 100.0%
* Incidents with pursuit fatalities in WA since 2015

Agencies

Agencies introduce another counting metric, since multiple agencies may be involved in a single incident. In this section we identify every agency involved in at least one pursuit-related fatality, along with the number and type of incidents involved (“Each agency count”). This means that incidents will be multiply counted when incidents have multiple agencies involved, and the totals cannot be compared to those in previous sections. For cross-reference, we also include a graph with the multi-agency fatalities grouped together (“Multi-agency count”).

By type

Each agency count
df <- agency.incident.p.long  %>%
  group_by(agency.type, Incident=incident.type) %>%
  summarise(Number = n()) %>%
  group_by(agency.type) %>%
  mutate(Total = sum(Number)) %>%
  mutate(Percent = Total/nrow(incidents.p))

p <- ggplot(df, 
            aes(x = reorder(agency.type, Total), y = Number, 
                fill = Incident,
                text = paste("Incident: ", Incident, "<br>",
                             "Number: ", Number))) +

   geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
                size = 3, nudge_y = 1) +
  
  labs(title = "Pursuit Incidents by Agency Type: Each agency count*",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "Agency type",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci)

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Incidents are counted more than once if multiple agencies are involved.

Multi-agency count
df <- incidents.p  %>%
  group_by(agency.type, Incident=incident.type) %>%
  summarise(Number = n()) %>%
  group_by(agency.type) %>%
  mutate(Total = sum(Number)) %>%
  mutate(Percent = Total/nrow(incidents.p))

p <- ggplot(df, 
            aes(x = reorder(agency.type, Total), y = Number, 
                fill = Incident,
                text = paste("Incident: ", Incident, "<br>",
                             "Number: ", Number))) +

   geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
                size = 3, nudge_y = 1) +
  
  labs(title = "Pursuit Incidents by Agency Type: Multi-agency count*",
       caption = "WA State since 2015; y-axis=pct, bar label=count",
       x = "Agency type",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci)

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Each incident only counts once

By name

For this graph, we report only the “each agency count” statistics.

df <- agency.incident.p.long  %>%
  mutate(agency = gsub("Washington", "WA", agency),
         agency = gsub("County Sheriff's Office", "Co SO", agency),
         agency = gsub("Police Department", "PD", agency),
         agency = if_else(grepl(",", agency), "Multiple agencies", agency)) %>%
  group_by(agency, Incident=incident.type) %>%
  summarise(Number = n()) %>%
  group_by(agency) %>%
  mutate(Total = sum(Number)) %>%
  mutate(Percent = Total/nrow(incidents.p))

p <- ggplot(df, 
            aes(x = reorder(agency, Total), y = Number, 
                fill = Incident,
                text = paste("Incident: ", Incident, "<br>",
                             "Number: ", Number))) +

  geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
                size = 2, nudge_y = 0.6) +
  
  labs(title = "Pursuit Incidents by Agency: Each agency count*",
       caption = "WA State since 2015",
       x = "Agency",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci) +
  scale_y_continuous(breaks = 0:(max(df$Total)+1), 
                     labels = as.character(0:(max(df$Total)+1))) +
  theme(axis.text.y=element_text(size=6)) +
          
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()
  • Incidents are counted more than once if multiple agencies are involved.

Geography

By County

df <- incidents.p  %>%
  group_by(county, Incident=incident.type) %>%
  summarise(Number = n()) %>%
  group_by(county) %>%
  mutate(Total = sum(Number)) %>%
  mutate(Percent = Total/nrow(incidents.p))

p <- ggplot(df, 
            aes(x = reorder(county, Total), y = Number, 
                fill = Incident,
                text = paste("Incident: ", Incident, "<br>",
                             "Number: ", Number))) +

   geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  geom_text(aes(y = Total,
                label = scales::percent(Percent, acc=1)),
                size = 3, nudge_y = 1) +
  
  labs(title = "Pursuit Incidents by County",
       caption = "WA State since 2015",
       x = "County",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci) +
    scale_y_continuous(breaks = 0:max(df$Total), labels = as.character(0:max(df$Total))) +
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

By City

df <- incidents.p  %>%
  group_by(city, Incident=incident.type) %>%
  summarise(Number = n()) %>%
  group_by(city) %>%
  mutate(Total = sum(Number)) %>%
  mutate(Percent = Total/nrow(incidents.p))

p <- ggplot(df, 
            aes(x = reorder(city, Total), y = Number, 
                fill = Incident,
                text = paste("Incident: ", Incident, "<br>",
                             "Number: ", Number))) +

   geom_bar(stat="identity",  color = "grey", alpha = 0.8) +
  
  # geom_text(aes(y = Total,
  #               label = scales::percent(Percent, acc=1)),
  #               size = 3, nudge_y = 0.5) +
  
  labs(title = "Pursuit Incidents by City",
       caption = "WA State since 2015",
       x = "City",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci) +
  scale_y_continuous(breaks = 0:max(df$Total)) +
  
  theme(axis.text.y = element_text(size = 6)) +
  
  coord_flip()

ggplotly(p, tooltip = "text") %>% reverse_legend_labels()

Trend over time

For incident counts, in contrast to fatality counts, we present only calendar and legislative year graphics. Neither provides an accurate “apples-to-apples” comparison.

Calendar year

This is a common way to aggregate the fatality counts into standardized time units in a single graphic, but it does not give a clear picture of the policy impacts because the laws changed in the middle of 2021 and the middle of 2024.

df <- incidents.p %>%
  group_by(Year=year, incident.type) %>%
  summarize(Number = n()) %>%
  left_join(allrows.calyr.inci, .) %>%
  mutate(Number = tidyr::replace_na(Number,0)) %>%
  group_by(Year) %>%
  mutate(Total = sum(Number))



p <- ggplot(df, aes(x=Year, y=Number, 
                    fill = incident.type)) +
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +
  
  annotate("text",
           x = max.yr,
           y = df$Total[nrow(df)]+1,
           label = "YTD", size = 3) +
  
  labs(title = "Pursuit incidents by calendar year",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci) +
  scale_x_continuous(breaks = min.yr:max.yr)
  
ggplotly(p) %>% reverse_legend_labels()

Legislative year

Aggregating the fatality counts into standardized legislative years does a somewhat better job of showing the policy impacts, but is still not accurate because the standardized years don’t exactly line up with when legislation becomes effective. Note also that the current legislative year is typically not yet complete, so should be interpreted with care because the total may rise (it will not decline). Increases from previous years to the current year are meaningful but potentially under-estimate the difference, declines observed from previous years to the current year are not meaningful since this year’s total is not complete.

df <- incidents.p %>%
  filter(date > as.Date("2015-07-30")) %>% # to get the first complete year
  group_by(leg.year, incident.type) %>%
  summarize(Number = n()) %>%
  left_join(allrows.legyr.inci, .) %>%
  mutate(Number = tidyr::replace_na(Number,0)) %>%
  group_by(leg.year) %>%
  mutate(Total = sum(Number),
         leg.year = gsub("Aug|Jul", "", leg.year))
 
ymax <- max(df$Total)
hb1054 <- max(which(df$leg.year == "2020-2021"))/3
sb5352 <- max(which(df$leg.year == "2022-2023"))/3
i2113 <- max(which(df$leg.year == "2023-2024"))/3

p <- ggplot(df, 
            aes(x=leg.year, y=Number,
                fill=incident.type)) +
  
  geom_bar(stat = "identity", color="grey", alpha = 0.8) +

  # policy period separators
  
  geom_vline(xintercept =  hb1054 + .5, color="grey") + 
  geom_vline(xintercept =  sb5352 + .5, color="grey") + 
  geom_vline(xintercept =  i2113 + .5, color="grey") + 
  
  annotate("text", 
           x = "2017-2018", 
           y = ymax + 1.5, 
           label = "Pre-reform", size = 3) +
  
  annotate("text", 
           x = "2021-2022", 
           y = ymax + 1.5, 
           label = "HB1054", size = 3) +
  
    annotate("text", 
           x = "2023-2024", 
           y = ymax + 1.5, 
           label = "SB5253", size = 3) +
  
  annotate("text", 
           x = "2024-2025", 
           y = ymax + 1.5, 
           label = "I2113", size = 3) +
  
  annotate("text",
           x = max(df$leg.year), # is a factor
           y = df$Total[nrow(df)] + 0.5,
           label = "LYTD", size = 3) +
  
  labs(title = "Pursuit vehicular fatalities by legislative year",
       x = "Legislative Year",
       y = "Number") +
  
  scale_fill_manual(values = cols.inci) +

  scale_y_continuous(limits = c(0, ymax+2),
                     breaks= 1:(ymax + 1)) +
  

  
  theme(axis.text.x = element_text(size = rel(0.7)))

  
ggplotly(p) #%>% reverse_legend_labels() 

Attempted stops

Attempted stops are defined as incidents when an officer signals a motorist to stop by activating their lights and/or siren, but the motorist flees and the officer does not pursue. Whether these incidents should be considered vehicular pursuits is unclear.

The definition of a pursuit in Washington was also codified into law by HB 1054 in RCW 10.116.060:


  1. For purposes of this section, “vehicular pursuit” means an attempt by a uniformed peace officer in a vehicle equipped with emergency lights and a siren to stop a moving vehicle where the operator of the moving vehicle appears to be aware that the officer is signaling the operator to stop the vehicle and the operator of the moving vehicle appears to be willfully resisting or ignoring the officer’s attempt to stop the vehicle by increasing vehicle speed, making evasive maneuvers, or operating the vehicle in a reckless manner that endangers the safety of the community or the officer.

Note this definition does not require that the officer pursue the fleeing vehicle. Attempted stops would appear to meet this definition of pursuit.

There are incidents in our dataset that appear to be attempted stops. Our ability to identify these depends on what is reported in the supporting document. This is typically a news report, which in turn often relies on official police press releases or statements, so there are multiple opportunities for mis-characterization. It also seems likely that such incidents are more likely to be ignored or misreported by the media, so we miss them altogether.

Given the ambiguous status of these “attempted stops”, and the greater likelihood that they will not be captured accurately in our data, we have chosen to exclude them from the pursuit analysis above.

But these incidents are dangerous; they trigger the same fear and flight reactions in the subject, setting in motion a sequence of events that can lead to accidents, injuries and fatalities – just like active pursuits.

One example is an incident in Marysville, WA on August 29, 2020. According to the news report, an officer was on her way to another call around 2am when she saw a motorist doing donuts in the roadway. The officer activated her emergency lights to signal the motorist to stop, and allegedly he sped off but she did not pursue him. Within a minute he killed a man on a bicycle, and then crashed through the bedroom of a duplex killing a 97 year old woman asleep in her bed.

In this section we present information on the attempted stop incidents we do observe in our data, noting again the caveat that we may be missing many of these incidents.

Of the 12 attempted stop incidents we observe in our data, 4 involved multiple fatalities.

These incidents are shown on the map below. More information on each case can be obtained by hovering over, or clicking, the incident icon on the map. The list of fatalities is in the “Table of fatalities” tab, which can be downloaded.

Map of incidents

iconset <- awesomeIconList(
  single = makeAwesomeIcon(
    icon = 'user',
    library = 'fa',
    iconColor = 'white',
    markerColor = ~ inci.mapcolor
  ),
  mult = makeAwesomeIcon(
    icon = 'users',
    library = 'fa',
    iconColor = 'white',
    markerColor = ~ inci.mapcolor
  ))

iconset.legend <- awesomeIconList(
  `B or P killed` = makeAwesomeIcon(
    icon = 'user',
    library = 'fa',
    iconColor = 'black',
    markerColor = 'red',
  ),
  `Subject killed` = makeAwesomeIcon(
    icon = 'user',
    library = 'fa',
    iconColor = 'black',
    markerColor = 'blue',
  ),
  `Multiple fatalities` = makeAwesomeIcon(
    icon = 'users',
    library = 'fa',
    iconColor = 'black',
    markerColor = 'white',
  ))

labs <- with(incidents.as, 
             as.character(paste("fatalities:", 
                                fatalities, '<br>',
                                "injuries:",
                                total.injuries, '<br>',
                                'by', agency, '<br>',
                                'date: ', format(date, format="%m/%d/%y"))))

map <- leaflet(
  data = incidents.as, 
  width = "100%") %>% 
  addTiles() %>%
  
  addAwesomeMarkers( ~ long, ~ lat,
                     popup = ~ url_click,
                     label = lapply(labs, htmltools::HTML),
                     icon = ~iconset[inci.mapmult]) %>%
  
  addLegendAwesomeIcon(iconSet = iconset.legend,
                       orientation = 'vertical',
                       title = htmltools::tags$div(
                         style = 'font-size: 10px;',
                         'Incident type'),
                       labelStyle = 'font-size: 8px;') %>%
  
  leaflet.extras::addResetMapButton()
map

Table of fatalities

fatalities.as %>%
  select(name, date, victim, county, agency, url_click) %>%
  mutate(agency = gsub("Washington", "WA", agency),
         agency = gsub("County Sheriff's Office", "Co SO", agency),
         agency = gsub("Police Department", "PD", agency),
         agency = gsub("State Patrol", "SP", agency)) %>%
  rename(`link to article` = url_click) %>%
  arrange(desc(date)) %>%
  DT::datatable(rownames = F,
                caption = "Persons killed after attempted stops since 2015",
                filter = 'top',
                escape = FALSE,
                extensions = 'Buttons', 
                options = list(
                  dom = 'Bfrtip',
                  buttons = c('copy', 'csv', 'excel', 'pdf', 'print')) )

Was it worth it? Some examples

This report has documented some of the collateral damage caused by police pursuits. No pursuit is begun with the intention of killing uninvolved bystanders, but every pursuit brings that risk. Is the risk worth it? Consider the incidents below.

  • Kimberly Winslow was killed when she crashed into a tree while being pursued by Tacoma police for an alleged speeding violation. Her 9 year old son was in the car with her at the time, he was injured but survived.

  • State Trooper Justin Robert Schaffer was killed while laying down spike strips to disable a fleeing vehicle during a pursuit. He was hit by the fleeing vehicle. The pursuit started when a deputy with the Thurston County Sheriff’s Office identified a suspect in a shoplifting incident from the day before and initiated a traffic stop.

  • Kent Officer Diego Moreno was also killed laying down spike strips, but he was hit by the patrol car that was chasing the subject. The pursuit began when the subjects allegedly fired a gun in the air during a dispute in a parking lot at a bar and restaurant, and fled when they saw the police car.

  • Delilah Minshew, 6 yrs old, and Timothy Escamilla, 8 yrs old A speeding car going the wrong way on I-82 caused a head-on collision that killed two children in the other car. Multiple officers, from both the Washington State Patrol and the Sunnyside police department had begun pursuits of this vehicle in the previous hour, but terminated them due to safety concerns. The driver was charged with DUI, and under the WA state pursuit policy, reasonable suspicion of DUI allowed for pursuit.

    At the time of the crash, the final pursuit (4 in total) had been terminated 10 minutes earlier. For that reason, this case is classified as “pursuit-involved” rather than “active pursuit,” and is not included in the active pursuit vehicular fatality count in the graphic above (see the next section and the Data section of the report for more details on definitions). This case is included in the analysis above where pursuit-involved incidents are examined.

    A similar incident involving a wrong way driver on an interstate highway was handled differently, and resulted in no fatalities.

Data

Sources

The data we do use

This report is based on a locally maintained dataset focused on WA State. The data are updated about once each week, pulling, cleaning and merging data from two active national projects:

We incorporate data from one legacy project:

And the data from another legacy project are preserved in the cases from MPV:

In addition we conduct independent searches for incidents in WA state that these national projects may have missed, using a mix of google alerts and searches of WA-specific sources like medical examiner reports, independent investigation reports, social media, obituaries and public disclosure requests.

The primary data source is MPV, but due to coverage limitations in the MPV project (primarily the exclusion of most pursuit-related fatalities) we augment their data with cases from IncarcerNation, legacy data from Fatal Encounters and locally identified incidents. Cases are linked and de-duplicated across source datasets, and all records in the final merged dataset include the original source case IDs.


For the purposes of this report, we call the resulting merged dataset the “WA local” dataset.


The scripts for scraping, cleaning and merging the datasets can be found in this GitHub repository: https://github.com/nextstepswa/WA-FEWP.

Breakdown by source of data

The data used across the different sections of this report includes all fatal encounters with police that have some vehicle involvement: pursuits, attempted stops and accidental vehicular homicides on and off duty (the latter we note but exclude from analysis) . These comprise 34% of all fatalities in the WA local dataset.

The breakdown of these data by source is shown in the tabs below. Many incidents are included in more than one dataset, some are included only in one, and there are multiple ways to present the coverage of each source and pattern of overlap.

Source coverage

The coverage of each data source can be assessed by the presence of the source ID tags by year, shown below. The columns for each data source show the number of cases with that source ID tag. The “Total Cases” column in the table represents the total cases in that year, not the sum across the data sources. Comparing the number of cases in each of the Data Source columns to each other and the total gives a sense of what fraction of that year’s cases were covered by each source, the overlap across the sources, and how that varies by year.

fatalities.vehicle.related <- fatalities.all %>%
  filter(!grepl("other", incident.type))

tab <- fatalities.vehicle.related %>%
  group_by(Year = as.character(year)) %>%
  summarize(FE = sum(!is.na(feID)),
            IN = sum(!is.na(inID)),
            MPV = sum(!is.na(mpvID)),
            WaPo = sum(!is.na(wapoID)),
            WaLocal = sum(!is.na(waID)),
            Total.Cases = n()
  ) %>%
  mutate(Percent = round(100*Total.Cases/sum(Total.Cases), 1)) %>%

  add_row(Year = "Total", summarise(., across(where(is.numeric), sum)))

tab %>%
  kable(caption = "Source Coverage by Year") %>%
  kable_styling(bootstrap_options = c("striped","hover")) %>%
  add_header_above(header = c(" " = 1, "Fatalities covered by each data source" = 5, "De-duplicated yearly totals"=2)) %>%
  row_spec(dim(tab)[1], bold = T)  %>%
  column_spec(which(names(tab)=="Cases"), bold=T) %>%
  column_spec(which(names(tab)=="Percent"), italic=T) %>%

  add_footnote(label = "Percents may not sum to 100 due to rounding",
               notation = "symbol")
Source Coverage by Year
Fatalities covered by each data source
De-duplicated yearly totals
Year FE IN MPV WaPo WaLocal Total.Cases Percent
2015 3 0 3 2 1 4 2.4
2016 7 0 4 4 1 8 4.7
2017 13 0 6 6 0 13 7.7
2018 10 0 5 4 0 10 5.9
2019 15 0 5 4 0 15 8.9
2020 16 0 6 5 1 17 10.1
2021 12 12 3 3 0 12 7.1
2022 0 15 10 10 21 21 12.4
2023 0 17 5 5 19 19 11.2
2024 0 24 3 2 26 26 15.4
2025 0 20 6 0 24 24 14.2
Total 76 88 56 45 93 169 100.0
* Percents may not sum to 100 due to rounding
Source overlap

Each case in the dataset can also be identified by the number of sources that include it, a direct measure of the overlapping sources of information. The breakdown of source overlap by year is shown below.

tab <- fatalities.vehicle.related %>% 
  count(Year = as.character(year), source.overlap) %>% 
  pivot_wider(names_from=source.overlap, values_from=n) %>% 
  mutate(across(where(is.numeric), ~replace_na(.,0))) %>%
  rowwise() %>%
  mutate(Total = sum(c_across(where(is.numeric)))) %>%
  ungroup() %>%
  add_row(Year = "Total", summarise(., across(where(is.numeric), sum)))
  
tab %>%
  kableExtra::kbl(caption = "Breakdown of fatalities by number of data sources and year") %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  add_header_above(header = c(" " = 1, "Number of data source(s) for each fatality *" = 4, " " = 1)) %>%
  row_spec(which(tab$Year == "Total"), bold=T) %>%
  add_footnote(label = "Most records in MPV and WA can be found in multiple sources, see other tabs for details on the overlap",
               notation = "symbol")
Breakdown of fatalities by number of data sources and year
Number of data source(s) for each fatality *
Year 1 2 3 4 Total
2015 1 1 2 0 4
2016 1 0 7 0 8
2017 0 0 13 0 13
2018 0 1 9 0 10
2019 0 1 14 0 15
2020 1 1 15 0 17
2021 0 0 0 12 12
2022 7 4 1 9 21
2023 4 10 1 4 19
2024 8 15 1 2 26
2025 9 9 6 0 24
Total 31 42 69 27 169
* Most records in MPV and WA can be found in multiple sources, see other tabs for details on the overlap

Primary source

When MPV includes an incident, that is our starting point for that case. Incidents from the other datasets are incorporated only when they fall outside of MPV’s inclusion criteria. In the table below, we show the primary source of cases by year: all cases covered by MPV are listed in that column, the additional cases contributed from FE (2015-21), IN (2021+) and WA local (2022+) are shown in the other columns.

tab <- fatalities.vehicle.related %>% 
  mutate(Source = factor(
    case_when(
      !is.na(mpvID) ~ "MPV",
      !is.na(inSource) ~ "IN",
      !is.na(feID) ~ "FE",
      !is.na(waID) ~ "WA local",
      TRUE ~ "other"),
    levels = c("MPV", "FE", "IN", "WA local"))
  ) %>%
  count(Year = as.character(year), Source) %>% 
  pivot_wider(names_from=Source, values_from=n) %>% 
  mutate(across(where(is.numeric), ~replace_na(.,0))) %>%
  rowwise() %>%
  mutate(Total = sum(c_across(where(is.numeric)))) %>%
  ungroup() %>%
  add_row(Year = "Total", summarise(., across(where(is.numeric), sum)))
  
tab %>%
  kableExtra::kbl(caption = "Primary data source by year") %>%
  kable_styling(bootstrap_options = c("striped", "hover")) %>%
  add_header_above(header = c(" " = 1, "Primary data source for each fatality *" = 4, " " = 1)) %>%
  row_spec(which(tab$Year == "Total"), bold=T) %>%
  add_footnote(label = "Most records in MPV and WA can be found in multiple sources, see other tabs for the overlap",
               notation = "symbol")
Primary data source by year
Primary data source for each fatality *
Year MPV WA local FE IN Total
2015 3 1 0 0 4
2016 4 1 3 0 8
2017 6 0 7 0 13
2018 5 0 5 0 10
2019 5 0 10 0 15
2020 6 1 10 0 17
2021 3 0 9 0 12
2022 10 9 0 2 21
2023 5 11 0 3 19
2024 3 17 0 6 26
2025 6 13 0 5 24
Total 56 53 44 16 169
* Most records in MPV and WA can be found in multiple sources, see other tabs for the overlap

Source dataset descriptions

Mapping Police Violence

Data: 2013+

Mapping Police Violence (MPV) aims to establish a comprehensive national open-source dataset of homicides by police, on and off duty. It includes fatal shootings and fatalities caused by tasers, physical beatings, restraint holds, chemical spray, police dog attacks, less-lethal force and vehicular homicides. Vehicular homicides are included in MPV only when the fatalities are directly caused by a police action: intentionally running someone over, and intentional collisions and vehicle disabling during a pursuit that leads to a fatal accident. As they note on their methodology page, these criteria result in the exclusion of most vehicle pursuit-related fatalities (however they also note that they have begun to track these pursuits internally, so their coverage may change in the future). Given this restriction, MPV coverage of the cases in this report is largely restricted to after-pursuit-homicides.

MPV has incorporated historical data from two legacy projects:

MPV merged and deduplicated the incidents from these two datasets, removed incidents that did not meet their inclusion criteria, added eligible incidents that were missed by both projects, kept the information from both datasets on the included incidents, and is now augmenting all incidents (back through 2013) with additional information, as well as updating with new incidents.

MPV is a project of the Campaign Zero organization. They follow the principles of transparent reproducible research, with a systematic, multi-level review and coding process that is published on their methodology page (recommended reading), and datasets provided in downloadable form to the public.

We download the MPV data from here: https://mappingpoliceviolence.us/s/MPVDatasetDownload.xlsx.


IncarcerNation

Data: 2021+

IncarcerNation (IN) maintains a comprehensive, searchable website listing every fatality that has occurred during any police encounter in the United States, regardless of type, and without judgment. This includes deaths from direct police use of force [gunshots, tasers, K9, and other immediate lethal police action], as well as fatalities linked to police activities and interactions controlled by police that lead to death. These encompass high-speed pursuits (including deaths of drivers, passengers, bystanders, and pedestrians), collisions involving police vehicles, drownings during police chases, falls from heights during pursuit, asphyxiation during restraint, and suicides occurring in the context of police operations, often during SWAT incidents. (source: IncarcerNation’s “About Us” page).

IN’s inclusion criteria are therefore much broader than MPV’s, and they are the only active project with coverage equivalent to the legacy Fatal Encounters project. While most of their incidents overlap with MPV, they are the unique source for pursuit-related fatalities.

IN does not make their dataset downloadable for the public, so we manually review and transcribe information for the cases they list in Washington state. During transcription, duplicate cases, cases from Washington DC and cases that turn out to be non-police related homicides are excluded. Many of the IN cases are also covered by MPV and the local WA project, but when IN is the primary source of information, we note that.

The IN website can be found here: https://incarcernation.com/


Fatal Encounters

Data: 2000-2021

Fatal Encounters (FE) is a legacy project that sought to establish a comprehensive national open-source dataset of all deaths during encounters with police. This project was active through December 31, 2021, includes records going back to 2000, and produced the largest compilation of persons killed during encounters with police that is publicly available: 31,641 fatalities at the time the project ended. It covers deaths by all causes during a police encounter, including suicides, accidents, killings by off-duty police and vehicular pursuit related fatalities. The vehicular pursuit coverage in FE is broader than MPV, as it includes all fatalities from accidents during a pursuit, so it captures bystanders killed by the fleeing subject.

Legacy FE data are captured by the dataset used in this report in two ways:

  • Cases included in the MPV dataset.

  • Cases excluded by MPV are recovered and included by us, and are used in this report.

We originally downloaded the FE data from their website: https://docs.google.com/spreadsheets/d/1dKmaV_JiWcG8XBoRgP8b4e9Eopkpgt7FL7nyspvzAsE/edit?gid=0#gid=0

We made many corrections to the FE data and harmonized the variables while FE was still updating. The scripts for that can be found on our legacy GitHub repository: https://github.com/nextstepswa/fewapo. We now just read in the cleaned, harmonized data (included in our current GitHub repository).


Washington Post

Data: 2015-2025

The Washington Post Fatal Force (WaPo) dataset is a legacy project that sought to create a national database of fatal shootings by on-duty police. It was actively updating from January 1, 2015 through December 31, 2024. There were 10,429 fatalities recorded at the time the project ended. Given the restriction to fatal shootings, WaPo coverage of the cases in this report is limited to after-pursuit homicides.

  • WaPo historical data has been incorporated by the MPV project into their database, and is integrated into the WA local dataset via MPV.

The WaPo data can be downloaded from their GitHub repository here: https://github.com/washingtonpost/data-police-shootings.


For all of our data sources, it is worth noting that:

  • None include deaths in custody after booking – so all deaths in jails and prisons are excluded.

  • All sources may be missing incidents.

A comparison of the cases found in each dataset is presented in the next section of this report.

There has typically been a 1-2 week lag in MPV updates, but it can sometimes be longer. The date shown in the “most recent data update” tab above is an indication of the current lag. As of this report, the last data updates were:

  • October 31 2025 for Mapping Police Violence
  • November 04 2025 for IncarcerNation
  • November 04 2025 for the WA local data

The data we don’t use

The official government source of data for police pursuit fatalities is the Fatality Analysis Reporting System (FARS) maintained by the National Highway Traffic Safety Agency (NHTSA). Locally, the Washington State Traffic Safety Commission (WTSC) collects and codes these data and sends them to the national program. We do not use these data for several reasons:

  • The official data have a long publication lag.

    Both the WTSC and FARS datasets are only updated once a year, and those updates can take several months to a year to be released. This time lag makes it impossible to use these datasets to assess impacts of recent policy changes. Note that in Washington, real time police traffic collision reports (PTCRs) can be accessed through the Washington State Patrol Collision Analysis Tool here, but these do not identify pursuit-related incidents.

  • The official data do not include after-pursuit fatalities.

    FARS is a program designed to provide data on fatalities from vehicle accidents only. After-pursuit fatalities are not captured by this system.

  • The official data likely undercount pursuit vehicular fatalities.

    The WTSC and FARS were not originally designed to provide accurate data on pursuit fatalities. The “police pursuit involved” tag was added in 1994 to FARS (p. 91, FARS Users Manual). The way in which this is captured likely varies across the states. Here in WA, the state WTSC tags an incident as pursuit-related through a labor-intensive manual coding of the law enforcement narrative documents submitted with the Police Traffic Collision Report (PTCR). If the pursuit is not mentioned in the narrative, if there is no narrative, or if the coder fails to tag a case, a pursuit incident will fail to be identified. The likelihood that this results in under-identification of pursuit-related fatalties was acknowledged by the Research Director of the WTSC in a recent interview.

    Incomplete coverage of fatalities related to police activities is unfortunately the norm in official datasets. Homicides by police have been found to be undercounted by about 50% in official government data sources like the Arrest Related Death Program, the National Vital Statistics System and the Uniform Crime Reports. The most recent analysis to have replicated this finding is from the Institute for Health Metrics and Evaluation at the UW in 2021, published in the Lancet, one of the most respected peer-reviewed science publications in the world. You can access that paper online here.

    It is worth noting that the undercounts were documented and quantified by comparing official data to open-source data like MPV and Fatal Encounters. The open source methodology is now recommended even by federal agencies as a way to improve official data collection.

  • The official data do not provide key information on the individual incidents.

    FARS also does not include information on the law enforcement agenc(ies) involved in the pursuit. The local WTSC data has information on the agency that reported the incident and the agency that is investigating the incident, which may or may not be the agency involved in the pursuit.

    By contrast, detailed incident-based information is available in the data from Fatal Encounters, MPV and Incarcernation. The document link provided for each case in these datasets contains a wealth of additional contextual information, and serves as a springboard for further research on individual cases. These media reports also help to remind us that each of these “cases” is a person, someone from our community, and not just a number.

The data sources we rely on are not perfect. They also likely undercount the true number of fatalities associated with pursuits, as the search methods used by the projects rely on the incidents leaving a digital signature online, and not all pursuit fatalities will be reported this way. Our data sources do, however, provide more complete information, on a wider range of cases, and in a more timely manner, than the official data.

The number of fatalities we report here gives a lower bound on the true number vehicle pursuit-related fatalities. There may be more, but there will not be less.


Coding

The original data sources are not designed to facilitate direct analysis of vehicular pursuits. So we have identified and coded these cases by hand. We used two independent coders for all records in Washington State from January 2015 to December 2023 to establish a reliable rubric. Cases since then are typically coded by one person.

Data cleaning

We begin with a dataset that merges information on fatalities in WA state from the MPV, FE, WaPo, IN and the WA local datasets. The data are cleaned and new variables constructed to facilitate analysis. Any errors found are corrected. Updates to the cleaned dataset are made a few times a month.

More information can be found in this report, which also has links to the GitHub repository that hosts all of the basic data cleaning and analysis scripts.

Case inclusion/exclusion in this report

The source dataset keeps track of all persons killed during police encounters, regardless of the cause of death. For this pursuit report we include/exclude the following types of cases:

Inclusion

  • We retain vehicular homicides committed by the driver fleeing a police pursuit. This is a key contributor to the risks that police pursuits pose to the general public.

  • We retain after-pursuit suicides. This term refers to a person taking their own life with a gun, not to “suicide by cop.” The classification is based on the media report, which typically relies on a coroner’s or medical examiner’s determination. These cases are identified separately in the report tables and graphics.

Exclusion

  • We exclude fatalities from non-pursuit related on- or off-duty officer accidents (n = 8). It is worth noting that some of these have led to substantial public controversy and dismissal of the officer involved.

  • We exclude fatalities resulting from encounters with police that have no pursuit involvement (n = 328).

Pursuit review

All cases in the merged WA local dataset were reviewed for evidence of pursuit involvement and coded into categories.

We reviewed all evidence available in the original source datasets, including variables coded by FE, IN, MPV and WaPo and the link to the original verification document (typically a news article). We conducted additional online searches to find other media reports, coroner/ME reports, social media posts, and Law Enforcement Agency announcements. Using this information we classified cases into the following categories:

  • Active Pursuit – vehicular homicides from an active pursuit (e.g., a crash-related fatality, or someone getting run over).

  • Terminated pursuit – vehicular homicides from an active pursuit that was reportedly terminated just before the accident occurred. “Just before” means within a minute or a mile.

  • Involved pursuit – a vehicle pursuit occurred during the incident, but it had finished before the person was killed. Typically the person killed in these cases is a fleeing subject who is either shot by police at the end of the chase, or their death is ruled a suicide due to a self-inflicted gunshot. Less commonly, if police terminate a pursuit the subject may continue to flee for some time, and cause a vehicular homicide that happens well after the end of the pursuit. In these cases the fatality may be an uninvolved bystander or passenger.

  • Attempted stop – vehicular homicides that occur when the subject flees a traffic stop but is not pursued. We often have to rely on a media report of the law enforcement statement that there was no pursuit, but the patrol car lights and/or siren may have been activated.

  • Vehicle accident – vehicular homicides by police that are not related in any way to a pursuit (e.g., an on- or off-duty officer ran someone over and killed them).

  • Not pursuit related – all other incidents we reviewed and determined were not related to vehicle stops/accidents/pursuits.

Final categories

We grouped the active and terminated pursuits together into the “Pursuit vehicular homicide” category, and split the involved pursuits into “After pursuit homicides” and “After pursuit suicides”.

fatalities.all %>%
  mutate(`Pursuit code` = factor(
    if_else(pursuit.type == "Involved pursuit", incident.type, pursuit.type),
    levels = c("Active pursuit", "Terminated pursuit",
               "After pursuit homicide", "After pursuit suicide",
               "Attempted stop", "Vehicle accident - on duty", "Vehicle accident - off duty",
               "Not pursuit related"))
  ) %>% 
  count(`Pursuit code`) %>%

  kbl(caption = "Coding results",
      align = "lr") %>%
  pack_rows("Pursuit vehicular fatalities", 1,2) %>%
  pack_rows("After pursuit fatalities", 3,4) %>%
  pack_rows("Other vehicle related", 5,7) %>%
  kable_styling(bootstrap_options = "striped") %>%

  add_footnote("Table data include all fatalities during a police encounter.",
               notation = "symbol")
Coding results
Pursuit code n
Pursuit vehicular fatalities
Active pursuit 55
Terminated pursuit 7
After pursuit fatalities
After pursuit homicide 70
After pursuit suicide 12
Other vehicle related
Attempted stop 17
Vehicle accident - on duty 6
Vehicle accident - off duty 2
Not pursuit related 328
* Table data include all fatalities during a police encounter.

The majority of the report focuses on pursuit vehicular fatalities and after-pursuit fatalities. Fatalities from attempted stops are examined in a separate section. Vehicular accidents and other deadly force fatalities are excluded.


Coding vehicular fatality victim types

Vehicular fatalities are defined as cases where the cause of death is a vehicle. This includes fatalities from active and terminated pursuits, attempted stops and vehicle accidents. There are also a few “Involved pursuit” incidents where a vehicle is the cause of death. In one the subject’s car was stopped after a pursuit and he fled by foot onto Interstate 5 where he was hit and killed. In another the officer was making a u-turn at the start of the pursuit, and the subject crashed into them and died.

For each vehicular fatality we coded

  • The status of the person(s) killed: subject (the driver of the vehicle being pursued), passenger (in the fleeing vehicle), bystander or officer.

  • Whether there were any additional injuries noted in the supporting documents (again coding status of the injured person).


What we miss

Our ability to identify and track these incidents is not perfect. The two key limitations are:

  1. This is a fatality-based dataset, not a dataset of pursuits.

The data we have only includes pursuits from incidents that result in at least one fatality – so:

  • We miss pursuits that result in accidents that cause injuries and/or property damage only

  • We miss pursuits that end without accidents or fatalities

For this reason, we are not able to estimate the total number of pursuits, or the fraction of pursuits that lead to fatalities, injuries or property damage.

  1. We rely largely on online documents to find and code these cases.
  • We miss incidents that do not leave an online trace, or if our search methods do not capture that trace

  • We miss incidents if the document reports the fatality but fails to report on the pursuit

  • We may misclassify a case if the document has not included the necessary information

We rely on the level of detail reported in the online documents to find these cases. Those documents, in turn, typically rely on a press release or social media post from the involved law enforcement agency. The law enforcement description of the event is rarely verified with independent sources, unless it becomes a high profile case and comes under scrutiny.


Ambiguous cases

In 2 incidents, the information available in the media report left it somewhat unclear whether the incident should be classified as a pursuit or as an attempted stop: Robert Bray (9/25/2022) and Stephanie Laguardia (3/16/2022). We coded these as pursuits, given the balance of the evidence. If these cases were instead coded as attempted stops, they would be removed from the pursuit vehicular fatality count. Since both of these cases occurred during the HB1054 period, this would reduce both the number of fatalities and the annualized fatality rate during that period, and would mean that we have underestimated the protective effect of the pursuit safety policy.

In 1 incident, the events lay on the boundary of the pursuit category: Sergey Pavlovich (6/28/2019). Here the officer reportedly was making a U-turn in response to a 911 call for speeding motorcycles, and saw the motorcycles approaching him at the time. Pavlovich crashed his motorcycle into the patrol car and was killed. It is unclear whether the officer intended to give pursuit. We coded this case as “pursuit-involved”, but it could also be considered a “Vehicular accident”. Since neither classification is included in the cases used to estimate policy impact the decision has no effect on those estimates.

In 1 incident, an unusual set of events could be construed as either “pursuit-involved” or “terminated pursuit”. This incident involved a speeding motorist who was actively pursued multiple times over the course of an hour by 4 different state patrol troopers and by local police. In each instance, the pursuit was terminated for safety reasons, as the motorist exceeded 100 mph and was weaving in and out of traffic on both highways and city streets. The last pursuit was terminated 10 minutes before the motorist, still travelling at high speed and headed the wrong way down a highway exit ramp, crashed into another vehicle, killing 2 children in that vehicle (Delilah Minshew and Timothy Escamilla, 2/28/2023). Since the pursuit was terminated 10 minutes before the crash, and our definition of terminated pursuits requires termination within a minute or a mile of the vehicular homicide, we classified this incident as “pursuit-involved”. If this were classified instead as a “terminated pursuit”, the definition change would require reclassifying other cases for consistency, and without doing that the change in the estimated policy impacts can not be calculated.


Download the data

Persons killed

This table lists all fatalities in the dataset, with some basic information, the pursuit related coding for this incident, and a link to a verification document for further details. This document can be used as a starting place for research on this case.

“LegDist” is the WA legislative district. “Type” is the detailed pursuit classification for each case.

Buttons for downloading the data are at the top of the table. The table columns can be filtered and sorted as well.

fatalities.p %>%
  mutate(Type = factor(
    if_else(pursuit.type == "Involved pursuit", incident.type, pursuit.type)),
    LegDist = as.character(WA_District)
    ) %>%
  select(Name=name, Date=date, Victim=victim, County=county, Agency=agency, 
         LegDist, Type, Link = url_click) %>%
  mutate(Agency = gsub("Washington State Patrol", "WSP", Agency),
         Agency = gsub("Washington", "WA", Agency),
         Agency = gsub("County Sheriff's Office", "Co SO", Agency),
         Agency = gsub("Police Department", "PD", Agency)) %>%
  arrange(desc(Date)) %>%
  DT::datatable(rownames = F,
                caption = "Persons killed during police encounters since 2015",
                filter = 'top',
                escape = FALSE,
                extensions = 'Buttons', 
                options = list(
                  dom = 'Bfrtip',
                  buttons = c('copy', 'csv', 'excel', 'pdf', 'print')) )

Incidents

This table lists the pursuit-related incidents that resulted in fatalities, with information on the agency (or agencies) involved, fatalities and injuries. Pursuit-related incidents include pursuit vehicular fatalities from active and terminated pursuits and after-pursuit homicides and suicides.

Buttons for downloading the data are at the top of the table, and the columns can be filtered and sorted.

incidents.p %>%  
  mutate(LegDist = as.character(district)) %>%

  mutate(agency = gsub("Washington State Patrol", "WSP", agency),
         agency = gsub("Washington", "WA", agency),
         agency = gsub("County Sheriff's Office", "Co SO", agency),
         agency = gsub("Police Department", "PD", agency)) %>%
  select(Agency=agency, Date=date, LegDist, Fatalities=fatalities,
         `P/O/B killed` = pbo.killed, 
         `P/B injured` = pb.injured) %>%
  arrange(desc(Date)) %>%

  DT::datatable(rownames = F,
                caption = "Incidents by agency since 2015",
                filter = 'top',
                extensions = 'Buttons', 
                options = list(
                  dom = 'Bfrtip',
                  buttons = c('copy', 'csv', 'excel', 'pdf', 'print')) )

GitHub respository

This report follows the principles of transparent, reproducible science. All of the scripts, data and software are open source and freely available to the public, online.


The scripts needed to reproduce this report are posted on our public GitHub Pursuits Repository.


Note that the source data files must first be constructed using the scripts in the GitHub WA Fatal Encounters With Police (WA-FEWP) repository.

The software used to produce this report comes from the open-source R project. You can view the code in the report itself by clicking the Code buttons in the right margin, or you can download all of the scripts from the repository.

R is free and runs on most Unix, Windows and MacOS operating systems. The report script uses rmarkdown and knitr.

  • If you find a bug in our code, please let us know by posting it as an issue in the repository.

  • If you have a question about the methodology, or the data, or the topic in general, please start a thread on the repository discussions page (note: you’ll need a GitHub account – they’re free, just follow the instructions at the link).

  • If you want to get involved, please email us at Next Steps Washington


: : : :


Pursuit legislation

The current RCW can be found online here

2021 legislation

The full text of HB 1054 as passed by the WA State legislature in 2021 can be found online here.

The section addressing vehicle pursuits reads:

knitr::include_graphics(here::here("Legislation", "HB1054-SECTION.PNG"))

2023 legislation

The full text of SB 5352 as passed by the WA State legislature in 2023 can be found online here.

The section addressing the key changes to the vehicle pursuit policy reads:

knitr::include_graphics(here::here("Legislation", "SB5352screenshot.png"))

2024 legislation

The full text of Initiative 2113 as passed by the WA State legislature in 2024 can be foun online here.

The sections changed by Initiative 2113 read:

knitr::include_graphics(here::here("Legislation", "I2113screenshot.png"))