library(ggplot2)
library(plotly)
library(kableExtra)
library(dplyr)
library(forcats)
library(here)
library(leaflet)

# For 2010-2014 data, only have in FE
load(file = here("data-outputs", "CleanData.rda"))

startmo = 1  # Jan 2010
startyr = 2010

finaldata_2010 <- fe_clean %>% filter(year >= startyr & st == "WA")

# 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_2010 %>% 
  filter(circumstances != "Suicide" &
           feID != 28698 & #deputy crash while having stroke
           feID != 25804 & #next 2 killed by suspect, not police
           feID != 25805) %>%
  arrange(date)

# for geocoded LDs
with(homicides, write.csv(cbind(feID,latitude,longitude),
                          here::here("data-outputs",
                                     "geocodes2010.csv")))

all.cases <- dim(finaldata_2010)[1]
last.case <- dim(homicides)[1]

last.date <- max(homicides$date)
last.name <- ifelse(homicides$lname[last.case] == "Unknown", 
                    "(Name not released)",        
                  paste(homicides$fname[last.case],
                        homicides$lname[last.case]))
last.age <- homicides$age[last.case]
last.agency <- homicides$agency[last.case]
last.cod <- homicides$cod[last.case]
tot.by.yr <- table(homicides$year)
tot.this.yr <- tot.by.yr[[length(tot.by.yr)]]
num.suffix <- ifelse(tot.this.yr == 1, "st",
                     ifelse(tot.this.yr == 2, "nd",
                            ifelse(tot.this.yr == 3, "rd", "th")))

# Indices for plotting by time

curr_mo <- lubridate::month(Sys.Date())
curr_yr = lubridate::year(Sys.Date())

endyr = curr_yr-1 # last complete year
numyrs = endyr - startyr + 1

month = month.abb[startmo:12]
year = rep(startyr, length(month))
for(i in 1:(numyrs-1)) {
  #print(i)
  thisyr = startyr+i
  #print(thisyr)
  year <- c(year, rep(thisyr, 12))
  month <- c(month, month.abb)
}
year <- c(year, rep(curr_yr, curr_mo-1))
month <- c(month, month.abb[1:curr_mo-1])

## Month index for date plotting

index <- data.frame(year = year,
                    month = month,
                    mo.yr = paste0(month, ".", year))

Introduction

After winning over 60% of the statewide vote, Initiative 940 was passed into WA state law on December 6, 2018. In 2021, a package of 12 additional bills focused on police reform were passed by the state Legislature. This report tracks the number of persons killed by police in WA state from 2010 until now.

MOST RECENT DATA UPDATE:

  • Total homicides by police since 2010: 424

  • Last reported case: Dwayne Fields, 34 years old, on 2021-06-25 by Fife Police Department, Washington State Patrol

    Dwayne Fields is the 11th person killed by police in 2021. The cause of death is reported as Gunshot.

One out of every 5 persons killed in Washington state is killed by a law enforcement officer. (Roughly 250 homicide deaths are recorded each year in WA State. You can find the state’s death data here).


Where the data come from

The data in this report are updated at least once each week, pulling and merging from the Fatal Encounters project (https://fatalencounters.org/). Fatal Encounters includes all deaths during encounters with police; it does not include deaths in custody after booking.

This report is restricted to the cases that can be classified as homicides by police, it excludes cases identified in the Fatal Encounters dataset as suicides.


What is a homicide?

The deadly force incidents in this report are homicides. A homicide is simply defined as the killing of one person by another. In the context of this report it refers to any encounter with law enforcement officers that results in a fatality. Homicides normally result in a criminal investigation or inquest, but the word does not imply a crime has been committed.

  • The word homicide means only that the death was caused in some way by the officer.

  • It does not not mean the officer’s actions that led to the death were justified, or that they were unjustified.

There are many different types of homicides. In the U.S., these types and definitions vary across states, but there are some general similarities. The definitions below are taken from a useful online summary found here, based on California State laws.

Homicide
Homicide is the killing of one person by another. This is a broad term that includes both legal and illegal killings. For example, a soldier may kill another soldier in battle, but that is not a crime. The situation in which the killing happened determines whether it is a crime.

  • Murder is the illegal and intentional killing of another person. Under California Penal Code Section 187, for example, murder is defined as one person killing another person with malice aforethought. Malice is defined as the knowledge and intention or desire to do evil. Malice aforethought is found when one person kills another person with the intention to do so.

    In California, for example, a defendant may be charged with first-degree murder, second-degree murder, or capital murder.

    • First-degree murder is the most serious and includes capital murder – first-degree murder with “special circumstances” that make the crime even more egregious. These cases can be punishable by life in prison without the possibility of parole, or death.

    • Second-degree murder is murder without premeditation, but with intent that is typically rooted in pre-existing circumstances. The penalty for second-degree murder may be up to 15 years to life in prison in California.

    • Felony murder is a subset of first-degree murder and is charged when a person is killed during the commission of a felony, such as a robbery or rape.

  • Manslaughter is the illegal killing of another person without premeditation, and in some cases without the intent to kill. These cases are treated as less severe crimes than murder. Manslaughter can also be categorized as voluntary or involuntary.

    • Voluntary manslaughter occurs when a person kills another without premeditation, typically in the heat of passion. The provocation must be such that a reasonable person under the same circumstances would have acted the same way. Penalties for voluntary manslaughter include up to 11 years in prison in California.

    • Involuntary manslaughter is when a person is killed by actions that involve a wanton disregard for life by another. Involuntary manslaughter is committed without premeditation and without the true intent to kill, but the death of another person still occurs as a result. Penalties for involuntary manslaughter include up to four years in prison in California.

    • Vehicular manslaughter occurs when a person dies in a car accident due to another driver’s gross negligence or even simple negligence, in certain circumstances.


Interactive Map

You can click the numbered circles to reach the individual map pointers for each person killed by police.

  • 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 = homicides, width = "100%") %>% 
  addTiles() %>%
  addMarkers( ~ longitude,
              ~ latitude,
              popup = ~ url_click,
              label = ~ as.character(paste(name, "by", agency)),
              clusterOptions = markerClusterOptions())
map1
agencynum <- homicides %>%
  group_by(agency) %>%
  count() %>%
  rename(agency_num = n)

homicides <- right_join(homicides, agencynum)

map2 <- leaflet(data = homicides, width = "100%") %>% 
  addTiles() %>%
  addCircles(~longitude, ~latitude, 
             weight = 1, radius = ~sqrt(agency_num) * 5000, 
             label = ~ as.character(agency),
             popup = ~agency_num)

map2
map3 <- leaflet(data = homicides, width = "100%") %>% 
  addTiles() %>%
  addMarkers( ~ longitude,
              ~ latitude,
              popup = ~ url_click,
              label = ~ as.character(name))
map3

Breakdowns

Race

Table

The race of the victim is missing in 17% of the original data. Fatal Encounters employs an algorithm to try to impute these cases. Over half of the missing values are successfully imputed. These imputations are included in the analysis here.

tab <- homicides %>%
  mutate(raceImp = recode(raceImp,
    "API" = "Asian/Pacific Islander",
    "BAA" = "Black/African American",
    "HL" = "Hispanic/Latinx",
    "NA" = "Native American/Indigenous",
    "WEA" = "White/European American")
  ) %>%
group_by(raceImp) %>%
  summarize(Number = n(),
            Percent = round(100*Number/nrow(homicides), 1)
  ) %>%
  bind_rows(data.frame(raceImp="Total", 
                       Number = sum(.$Number), 
                       Percent = sum(.$Percent))) %>%
  rename(Race = raceImp) 

tab %>%
  kable(caption = "Breakdown by Race") %>%
  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")
Breakdown by Race
Race Number Percent
Asian/Pacific Islander 18 4.2
Black/African American 52 12.3
Hispanic/Latinx 45 10.6
Native American/Indigenous 18 4.2
White/European American 276 65.1
Unknown 15 3.5
Total 424 99.9
* Percents may not sum to 100 due to rounding

Plots

homicides %>%
  mutate(raceImp = recode(raceImp,
    "API" = "Asian",
    "BAA" = "Black",
    "HL" = "Latinx",
    "NA" = "Native",
    "WEA" = "White")
  ) %>%
  count(raceImp) %>%
  mutate(perc = n / nrow(homicides)) %>%
  ggplot(aes(x=raceImp, 
             y = perc, 
             label = n)) +
  # label = round(100*perc, 1))) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  geom_text(aes(y = perc), size = 3, nudge_y = .025) +
  labs(title = "Fatalities by Race",
       caption = "WA State since 2010; y-axis=pct, bar label=count") +
         xlab("Reported Race") +
         ylab("Percent of Total")

homicides %>%
  mutate(raceb = case_when(raceImp == "WEA" ~ "White",
                           raceImp == "Unknown" ~ "Unknown",
                           TRUE ~ "BIPOC"),
         raceb = fct_relevel(raceb, "Unknown", 
                             after = Inf)) %>%
  count(raceb) %>%
  mutate(perc = n / nrow(homicides)) %>%
  ggplot(aes(x=raceb, 
             y = perc, 
             label = n)) +
  geom_text(aes(y = perc), size = 3, nudge_y = .025) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Fatalities by Race",
       caption = "WA State since 2010; y-axis=pct, bar label=count") +
  xlab("Reported Race") +
  ylab("Percent of Total")

Discussion

Racial disparities in the risk of being killed by police are one of the most important factors driving the public demand for police accountability and reform. For that reason it is important to understand how these numbers can, or should not be used.

There are several things to keep in mind when interpreting the breakdown of cases by the race of the person killed in this report.

  1. Many case reports are missing data on race

These cases are denoted “Unknown” in the tables and plots in this report.

For the Fatal Encounters dataset, about 17% of the cases for WA State since 2010 do not have information that explicitly identifies the race of the person killed. The Fatal Encounters team uses an “imputation” model to try to predict race for these cases. A brief description of the methodology is online here. They are able to impute just over half of the missing cases with reasonable confidence, and we include these imputations in the breakdowns reported here. After imputations, about 4% of cases are still missing race.

  1. We are reporting the counts here, not per capita rates

Breaking the total count down by race, the largest single group of persons killed by police, among those whose race is known, are identified as White/European-American: 46% of all cases, and 53% of the cases with known race.

This might be used to support a statement like, “The majority of persons killed by police in WA state are white, there aren’t any racial disparities”. That would be incorrect, for two reasons.

  • First, the fraction of cases with unknown race, 4%, is large enough that it is possible that the majority of persons killed in WA state are BIPOC. If two-thirds of the unknown cases are persons of color, that would mean the majority of victims are BIPOC. Using the case counts, we are not able to say with certainty whether the majority of persons killed by police in WA state are White.

  • Second, the question of disparity can only be answered after controlling for the size of the WA state populations by race. The population of Washington State is overwhelmingly white – almost 80% as of 2020 source: WA State OFM. On that basis alone, even if all of the unknown race cases where White, their rate of fatal encounters with police would still be 23% lower than expected, given their population share. On a per capita basis, the rate of persons killed by police is therefore higher for BIPOC. In particular, Black/African Americans comprise only 4% of the WA population, but 15% of the persons killed by police: they are 3.7 times more likely to be killed by police on a per capita basis.

  1. In addition, there are other sources of uncertainty that should be kept in mind:
  • Racial self-identification in WA state includes about 5% of people who report two or more races when asked. This multiple-race classification does not exist in the data on persons killed by police, and it complicates the detailed calculation of per capita rates by race.

  • Hispanic/Latinx is an ethnicity classification that crosses several racial groups, primarily White, Black and Native American. These cases are identified in the Fatal Encounters dataset as a distinct racial group, rather than as a separate ethnicity classification. This also complicates the calculation of detailed per capita rates by race.

  • Because the race classifications here do not represent what the officer perceived the person’s race to be, we can’t answer the question of intention, or implicit bias, with certainty.


Cause of death

Plot

homicides %>%
  mutate(codb = case_when(cod == "Gunshot" ~ "Gunshot",
                          TRUE ~ "Other")
         ) %>%
  count(codb) %>%
  mutate(perc = n / nrow(homicides)) %>%
  ggplot(aes(x=codb, 
             y = perc, 
             label = n)) +
  geom_text(aes(y = perc), size = 3, nudge_y = .025) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Fatalities by Cause of Death",
       caption = "WA State since 2010; y-axis=pct, bar label=count") +
  xlab("Reported Weapon Used by Police") +
  ylab("Percent of Total")

Table

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

tab %>%
  kable(caption = "Breakdown by Cause of Death",
        col.names = c("Cause of Death", "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")
Breakdown by Cause of Death
Cause of Death Number Percent
Gunshot 327 77.1
Vehicle 55 13.0
Tasered 20 4.7
Asphyxiated/Restrained 7 1.7
Medical emergency 4 0.9
Beaten/Bludgeoned with instrument 3 0.7
Burned/Smoke inhalation 2 0.5
Drowned 2 0.5
Drug overdose 2 0.5
Other 2 0.5
Total 424 100.1
* Percents may not sum to 100 due to rounding

Victim armed

This information is in the process of being coded by the Fatal Encounters project. It is not available yet for 2021, or prior to 2013, so all cases in those years are coded “Unknown”.

Note that the media often rely on the law enforcement narrative when reporting this information, so the validity of these data are unknown.

Plot

homicides %>%
  count(weapon) %>%
  mutate(perc = n / nrow(homicides)) %>%
  ggplot(aes(reorder(weapon, perc),
             y = perc, 
             label = n)) +
  geom_text(aes(y = perc), size = 3, nudge_y = .025) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "Fatalities by Report of Victim Weapon",
       caption = "WA State since 2010; y-axis=pct, bar label=count") +
  xlab("Reported Weapon Used by Victim") +
  ylab("Percent of Total")

Table

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

tab %>%
  kable(caption = "Breakdown by Report of Victim Weapon (incomplete data)",
        col.names = c("Weapon", "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")
Breakdown by Report of Victim Weapon (incomplete data)
Weapon Number Percent
Alleged Firearm 135 31.8
Unknown 112 26.4
No weapon 94 22.2
Alleged Edged weapon 58 13.7
Other 25 5.9
Total 424 100.0
* Percents may not sum to 100 due to rounding

County

Not all counties are represented here. If there have been no fatalities, the county is not included in the plot or table.

Plot

homicides %>%
  group_by(county) %>%
  summarize(n = n(),
            perc = n / nrow(homicides)) %>%
  ggplot(aes(reorder(county, perc),
             y = perc, 
             label = n)) +
  geom_text(aes(y = perc), size = 3, nudge_y = .025) +
  geom_bar(stat="identity", fill="blue", alpha=.5) +
  labs(title = "County",
       caption = "WA State since 2010; y-axis=pct, bar label=count") +
  xlab("County where fatal encounter happened") +
  ylab("Percent of Total") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

Table

homicides %>%
  group_by(county) %>%
  summarize(Number = n(),
            Percent = round(100*Number/nrow(homicides), 1)
  ) %>%
  DT::datatable(rownames = F,
                caption = "Breakdown by County")

Agency/PD involved

WA State has about 260 Law Enforcement agencies, at the State, County, Local, Tribal and College/University levels (see this Wikipedia page for a list). Only those with a known officer-involved homicide are listed in the plot and table here.

homicides %>%
  group_by(agency) %>%
  summarize(Number = n(),
            Percent = round(100*Number/nrow(homicides), 1)
  ) %>%
  DT::datatable(rownames = F,
                caption = "Breakdown by Agency/PD of Involved Officer")

Online information availability

This information comes from Fatal Encounters. It takes the form of a single url to a news article that is available online. There are often multiple news articles available online, and they may report the conflicting details of the event, as well as conflicting perspectives on the justifiability of the use of lethal force.

The clickable urls are available in this report in the Interactive Map and Say their names sections. They should be treated as a place to start research, not as the definitive description of the event.

tab <- homicides %>%
  mutate(url_info = case_when(url_info == "" ~ "No",
                               is.na(url_info) ~ "No",
                               TRUE ~ "Yes")) %>%
  group_by(url_info) %>%
  summarize(Number = n(),
            Percent = round(100*Number/nrow(homicides), 1)
  ) %>%
  bind_rows(data.frame(url_info ="Total", 
                       Number = sum(.$Number), 
                       Percent = sum(.$Percent))) 

tab %>%
  kable(caption = "URL for news article in Fatal Encounters",
        col.names = c("Availability", "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")
URL for news article in Fatal Encounters
Availability Number Percent
Yes 424 100
Total 424 100
* Percents may not sum to 100 due to rounding

Date

Monthly Totals Over Time

  • The points show the monthly totals, and the line shows the smoothed trend in fatalities by month.

  • This is an interactive plot: You can hover over points to get the exact values for the number of cases for that month and year.

# we will only plot after current month has finished

dat <- homicides %>%
  group_by(year, month) %>%
  summarize(count = n()) %>%
  left_join(index, ., by = c("year", "month")) %>%
  mutate(count = tidyr::replace_na(count, 0),
         seqlab = paste0(year, ".", match(month.abb, month.abb)),
         sequence = 1:nrow(.))

xtx <- seq(0, length(dat$sequence), 3)+1 # x axis ticks
p <- ggplot(dat, aes(x = sequence, 
                     y = count,
                     text = count))  +
  geom_point(size=1, aes(color = factor(year))) +
  geom_smooth(span=1, col="grey")  +
  geom_vline(xintercept = 12*1:numyrs+1, col="grey") +
  labs(title = paste("Monthly fatalities by Year:",
                     month.abb[startmo], startyr, " - ",
                     month.abb[curr_mo-1], curr_yr),
       caption = "WA since 2010",
       color = "Year") +
  xlab("Month/Year") +
  ylab("Number") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  scale_x_continuous(breaks = xtx, 
                     label = dat$mo.yr[xtx])  + 
  #scale_color_brewer(palette="spectral") +
  theme(panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank())

ggplotly(p, tooltip = "text")

Monthly Totals by Year

  • The points show the monthly totals, and the lines show the smoothed trend in fatalities by month, for each year.

  • This is an interactive plot: You can hover over points to get the exact values for the cumulative number of cases for that month and year.

# we will only plot after current month has finished

p <- homicides %>%
  group_by(year, month) %>%
  summarize(count = n()) %>%
  left_join(index, .) %>%
  group_by(year) %>%
  mutate(count = tidyr::replace_na(count, 0),
         month = factor(month, levels=month.abb)) %>%
  ggplot(aes(x = month, 
             y = count, 
             color = factor(year),
             group = year,
             text = paste('Total =', count, '<br>', 
                          month, year))) +
  geom_point(size=1) +
  geom_line(stat = "smooth", span=1, alpha = 0.5) +
  #ylim(0, 200) +
  labs(title = "WA since 2010:  Monthly fatalities by Year",
       caption = "WA since 2010",
       color = "Year") +
  xlab("Month") +
  ylab("Number")

ggplotly(p, tooltip = "text")

Cumulative Totals by Month/Year

  • The lines show the cumulative total fatalities by month as the year progresses, for each year.

  • 2018 is excluded as we only have one month (December) for that year.

  • This is an interactive plot: You can hover over points to get the exact values for the cumulative number of cases for that month and year.

p <- homicides %>%
  group_by(year, month) %>%
  summarize(count = n()) %>%
  left_join(index, .) %>%
  filter(year != 2018) %>%
  group_by(year) %>%
  mutate(count = tidyr::replace_na(count, 0),
         cumulative = cumsum(count),
         month = factor(month, levels=month.abb)) %>%
  ggplot(aes(x = month, 
             y = cumulative, 
             color = factor(year),
             group = year,
             text = paste('Total =', cumulative, '<br>', 
                          month, '<br>', year))) +
  geom_line(size = 1.5, alpha = 0.5) +
  geom_point(size=1, alpha = 0.5) +
  labs(title = "WA since 2010:  Cumulative fatalities by Month and Year",
       caption = "WA State since 2010",
       color = "Year") +
  xlab("Month") +
  ylab("Number")

ggplotly(p, tooltip = "text")

Year to date, by Year

Here we plot the cumulative totals for year to date, using the last complete complete month of the current year, for each year.

  • The bars represent totals for year-to-date for each year, divided by cause of death: gunshot vs. all other causes.

  • This is an interactive plot: You can hover over bar segments to get the exact values for that cause of death in that year.

p <-  homicides %>%
  filter(match(month, month.abb) < curr_mo) %>%
  mutate(cod = ifelse(cod == "Gunshot", "shot", "other"),
         cod = factor(cod, levels = c("shot", "other")),
         year = as.character(year)) %>%
  group_by(year, cod) %>%
  summarize(n = n()) %>%
  mutate(percent = round(100*n / sum(n), 1)) %>%
  ggplot(aes(x = year,
             y = n, 
             label = percent,
             fill = cod)) +
  #geom_text(aes(y = n), size = 3, nudge_y = .025) +
  geom_bar(stat="identity", alpha=.5,
           position = position_stack(reverse=T)) +
  scale_fill_manual(values = c("cadetblue", "goldenrod")) +
  labs(title = paste0("Fatalities Jan-", 
                      month.abb[curr_mo-1], 
                      " by Year"),
       caption = "WA since 2010",
       x = "Year",
       y = "Number",
       fill = "Cause of\nDeath")

plotly::ggplotly(p)

Say their names

Name known

Of the 424 persons killed by police, 415 of the victim’s names are known at this time.

homicides %>%
  filter(name != "Unknown") %>%
  select(name, date, age=age, county, agency, url = url_click) %>%
  arrange(desc(date)) %>%
  DT::datatable(rownames = F,
                caption = paste("The Names We Know:  as of", scrape.date),
                filter = 'top',
                escape = FALSE)

Name Unknown

The remaining 9 of the victim’s names are not known at this time.

homicides %>%
  filter(name == "Unknown") %>%
  select(name, date, age=age, county, agency, url = url_click) %>%
  arrange(desc(date)) %>%
  DT::datatable(rownames = F,
                caption = paste("The Names We Don't Know:  as of", scrape.date),
                filter = 'top',
                escape = FALSE)