library(ggplot2)
library(kableExtra)
library(dplyr)
library(leaflet)

load(file = here::here("data-outputs", "WA2015.rda"))

# If need to rebuild the pursuits classification sheet
# # Select homicides
# # Remove suicides and some final cases that don't belong
# ## 25804-5 are the Tad Norman case in Lake City. 
# ## Not victims of police violence.
# ## they were killed by Norman
# 
# homicides <- finaldata_2015 %>% 
#   filter(circumstances.fe != "Suicide" &
#            feID != 28698 & #deputy crash while having stroke
#            feID != 25804 & #next 2 killed by suspect, not police
#            feID != 25805) %>%
#   arrange(date)
# 
# homicides <- homicides %>%
#   mutate(pursuits = case_when(cod.fe == "Vehicle" ~ "yes",
#                               cod.fe == "Pursuit" ~ "yes",
#                               grepl('vehicle|car|crash|speed|chase', description) ~ "maybe",
#                               TRUE ~ "no"
#                               ))

#table(homicides$cod.fe, homicides$pursuits)
#write.csv(homicides, here::here("data-outputs", "pursuits.csv"))
# clean up file and read back in

library(readr)
pursuits <- read_csv(here::here("data-outputs", "pursuits.csv"))

pursuits <- pursuits %>%
  filter(circumstances.fe != "Suicide" &
           feID != 28698 & #deputy crash while having stroke
           feID != 25804 & #next 2 killed by suspect, not police
           feID != 25805) %>%
  mutate(traffic = if_else(grepl('traffic stop', description), "yes", "no"),
         cod = case_when(cod.fe == "Vehicle" ~ "Vehicle",
                         cod.fe == "Gunshot" ~ "Gunshot",
                         TRUE ~ "Other"),
         date = lubridate::mdy(date)) %>%
    arrange(date)

pursuits940 <- pursuits %>%
  filter(date > lubridate::mdy("12/06/2018"))

Introduction

Data source

This report examines the role of “hot pursuit” and vehicle chases in law enforcement related deadly force incidents in WA State. The data come from the Fatal Encounters Project.

Definition of cases

  • Classification as a “pursuit” case was based on two things: vehicle related fatalities, and other fatalities that involved a high speed chase, even if the cause of death was ultimately due to something other than the chase itself. An example of the latter would be a vehicle chase, followed by an officer shooting and killing the suspect. The breakdown of the cause of death for the cases classified as pursuits is shown in the table below.

  • Our knowledge of the details of these incidents is incomplete – it relies on the level of detail reported in the media. So we may have missed some incidents, if the media failed to report on the chase.

  • These data only represent fatal incidents – not any other injuries that may result from hot pursuits.

pursuits %>%
  mutate(pursuits = factor(pursuits, levels=c("yes","no","maybe"))) %>%
  rename(Pursuit=pursuits, CauseOfDeath=cod) %>%
  gtsummary::tbl_cross(row=Pursuit, col=CauseOfDeath, percent="row" ) %>%
  gtsummary::modify_header(label = "**Classification**") %>%
  gtsummary::as_gt() %>%
  gt::tab_source_note(gt::md("*Deadly force incidents since Jan 1 2015 in WA State*"))
## Warning: The `.dots` argument of `group_by()` is deprecated as of dplyr 1.0.0.
Classification CauseOfDeath Total
Gunshot Other Vehicle
Pursuit
yes 23 (43%) 3 (5.6%) 28 (52%) 54 (100%)
no 157 (87%) 23 (13%) 0 (0%) 180 (100%)
maybe 7 (88%) 1 (12%) 0 (0%) 8 (100%)
Total 187 (77%) 27 (11%) 28 (12%) 242 (100%)
Deadly force incidents since Jan 1 2015 in WA State

Number of incidents

Here we break down all deadly force incidents to show the number of incidents due to hot pursuits, and the fraction this is of the total.

Since 2015

tab <- pursuits %>%
  group_by(pursuits) %>%
  summarize(Number = n()) %>%
  mutate(Percent = round(100*Number/sum(Number), 1)) %>%
  arrange(desc(Number)) %>%
  bind_rows(data.frame(pursuits ="Total", 
                       Number = sum(.$Number), 
                       Percent = sum(.$Percent))) 

tab %>%
  kable(caption = "Pursuit and vehicle-related deaths since 2015",
        col.names = c("Pursuit/Vehicle", "Number", "Percent")) %>%
  kable_styling(bootstrap_options = c("striped","hover")) %>%
  row_spec(row=dim(tab)[1], bold = T)  %>%
  add_footnote(label = "Percents may not sum to 100 due to rounding",
               notation = "symbol")
Pursuit and vehicle-related deaths since 2015
Pursuit/Vehicle Number Percent
no 180 74.4
yes 54 22.3
maybe 8 3.3
Total 242 100.0
* Percents may not sum to 100 due to rounding

Since I-940

tab <- pursuits940 %>%
  group_by(pursuits) %>%
  summarize(Number = n()) %>%
  mutate(Percent = round(100*Number/sum(Number), 1)) %>%
  arrange(desc(Number)) %>%
  bind_rows(data.frame(pursuits ="Total", 
                       Number = sum(.$Number), 
                       Percent = sum(.$Percent))) 

tab %>%
  kable(caption = "Pursuit and vehicle-related deaths since I-940",
        col.names = c("Pursuit/Vehicle", "Number", "Percent")) %>%
  kable_styling(bootstrap_options = c("striped","hover")) %>%
  row_spec(row=dim(tab)[1], bold = T)  %>%
  add_footnote(label = "Percents may not sum to 100 due to rounding",
               notation = "symbol")
Pursuit and vehicle-related deaths since I-940
Pursuit/Vehicle Number Percent
no 76 71.0
yes 26 24.3
maybe 5 4.7
Total 107 100.0
* Percents may not sum to 100 due to rounding

Agencies Involved

Since 2015

Plot by type of agency

tbl <- pursuits %>%
  filter(pursuits == "yes") %>%
  mutate(agencyType = case_when(grepl("Sheriff", agency) & 
                                  grepl("Police", agency) ~ "Multiple",
                                grepl("Sheriff", agency) ~ "County Sheriff",
                                grepl("Police", agency) ~ "Police Department",
                                grepl('State Patrol', agency) ~ "WA State Patrol",
                                TRUE ~ "Other")) %>%
  group_by(agencyType) %>%
  summarise(Number = n()) %>%
  mutate(Percent = Number/sum(Number)) %>%
  arrange(Number) 

  # bind_rows(data.frame(agencyType ="Total",
  #                      Number = sum(.$Number),
  #                      Percent = sum(.$Percent)))

 
ggplot(tbl,
       aes(x = reorder(agencyType, Percent), y = Percent, 
           label = Number)) +
  geom_text(aes(y = Percent), size = 3, nudge_y = .02) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Incidents by Agency Type",
       caption = "WA State since 2015; y-axis=pct, bar label=count") +
  xlab("") +
  ylab("Percent of Total")

Detailed Plot

tbl <- pursuits %>%
  filter(pursuits == "yes") %>%
  mutate(agency = gsub("Washington", "WA", agency),
         agency = gsub("County Sheriff's Office", "Cty SO", agency),
         agency = gsub("Police Department", "PD", agency)) %>%
  group_by(agency) %>%
  summarise(Number = n()) %>%
  mutate(Percent = Number/sum(Number)) %>%
  arrange(Number) 

ggplot(tbl,
       aes(x = reorder(agency, Percent), y = Percent, 
           label = Number)) +
  geom_text(aes(y = Percent), size = 3, nudge_y = .005) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Incidents by Agency",
       caption = "WA State since 2015; y-axis=pct, bar label=count") +
  xlab("") +
  ylab("Percent of Total") +
  coord_flip()

Detailed Table

pursuits %>%
  filter(pursuits == "yes") %>%
  group_by(agency) %>%
  summarize(Number = n()) %>%
  mutate(Percent = round(100*Number/sum(Number), 1)) %>%
  DT::datatable(rownames = F,
                caption = "Incidents by agency")

Since I-940

Plot by type of agency

tbl <- pursuits940 %>%
  filter(pursuits == "yes") %>%
  mutate(agencyType = case_when(grepl("Sheriff", agency) & 
                                  grepl("Police", agency) ~ "Multiple",
                                grepl("Sheriff", agency) ~ "County Sheriff",
                                grepl("Police", agency) ~ "Police Department",
                                grepl('State Patrol', agency) ~ "WA State Patrol",
                                TRUE ~ "Other")) %>%
  group_by(agencyType) %>%
  summarise(Number = n()) %>%
  mutate(Percent = Number/sum(Number)) %>%
  arrange(Number) 
 
ggplot(tbl,
       aes(x = reorder(agencyType, Percent), y = Percent, 
           label = Number)) +
  geom_text(aes(y = Percent), size = 3, nudge_y = .02) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Incidents by Agency Type",
       caption = "WA State since 2015; y-axis=pct, bar label=count") +
  xlab("") +
  ylab("Percent of Total") 

Detailed Plot

tbl <- pursuits940 %>%
  filter(pursuits == "yes") %>%
  mutate(agency = gsub("Washington", "WA", agency),
         agency = gsub("County Sheriff's Office", "Cty SO", agency),
         agency = gsub("Police Department", "PD", agency)) %>%
  group_by(agency) %>%
  summarise(Number = n()) %>%
  mutate(Percent = Number/sum(Number)) %>%
  arrange(Number) 

ggplot(tbl,
       aes(x = reorder(agency, Percent), y = Percent, 
           label = Number)) +
  geom_text(aes(y = Percent), size = 3, nudge_y = .005) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Incidents by Agency",
       caption = "WA State since 2015; y-axis=pct, bar label=count") +
  xlab("") +
  ylab("Percent of Total") +
  coord_flip()

Detailed Table

pursuits940 %>%
  filter(pursuits == "yes") %>%
  group_by(agency) %>%
  summarize(Number = n()) %>%
  mutate(Percent = round(100*Number/sum(Number), 1)) %>%
  DT::datatable(rownames = F,
                caption = "Incidents by agency")

Interactive Map

The map includes all hot pursuit incidents since Jan 1, 2015. You can click down to the map pointers for each person killed.

  • Hovering over the pointer brings up the name of the person killed and agency of the officer who killed them;

  • Clicking the pointer will bring up a url to a news article on the case (if available).

map1 <- leaflet(data = pursuits %>% filter(pursuits=="yes"), 
                width = "100%") %>% 
  addTiles() %>%
  addMarkers( ~ longitude,
              ~ latitude,
              popup = ~ url_click,
              label = ~ as.character(paste(name, "by", agency)),
              clusterOptions = markerClusterOptions())
map1