1 Introduction

With the 2020 pandemic, there were many unexpected changes that accompanied the deadly virus. Hospitals were unprepared to handle the influx of fearful and infected individuals, along with schools and jobs being forced to go virtual to protect the people from catching or spreading this virus. We wanted to explore one of these major changes and the possible effect it would cause. We landed on wanting to explore the effects that this change had on crime.

We want to examine if the pandemic caused any significant changes for crime rates within Seattle before, during, and after the pandemic. It’s important to examine the pandemics’ effect on crime rates, did crime rates ascend to normal levels once the pandemic ended, stay at reduced levels, or increase past pre-pandemics rates. Additionally, it’s important to examine the possible changes that the pandemic had on crime to see if it had any effect at all and if not, what were the factors that affected crime rates.

People’s familiarity with the mandatory lockdown and mental deficit that came with it, it can be reassuring to some that there was a possible positive side to the pandemic. If there were changes, what types of crime had been affected, like domestic abuse and break ins considering the risk of disease and a mandated lockdown. Furthermore, examining if there was a change in crime hot spots to see if the pandemic moved the location of crime.

2 Data and Methods

Datasets:

1.King County Sheriff’s Office Offense Reports (2020-Present) https://data.kingcounty.gov/Law-Enforcement-Safety/KCSO-Offense-Reports-2020-to-Present/4kmt-kfqf/about_data

2.Seattle Police Department Arrest Data https://data.seattle.gov/Public-Safety/SPD-Arrest-Data/9bjs-7a7w/about_data

We focused on Seattle-specific offenses occurring in 2020, 2022, and 2024. The offense report data provides key details such as crime type, location (zip code), time of occurrence, and reporting timestamps. Additionally, the arrest data from the Seattle Police Department includes longitude and latitude coordinates, enabling us to create heatmaps for a more visually intuitive interpretation of crime distribution.

However, we encountered missing and inconsistent data, particularly in zip codes and crime classifications. To address this, we applied data filtering and cleaning techniques to ensure a more accurate analysis.

Packages & Tools Used:

We used R and the following packages for data retrieval, processing, and visualization:

This methodology allowed us to effectively explore crime distribution, visualize high-crime areas, and analyze trends over time. The combination of structured data processing and visual analytics provided insights into how crime patterns have changed in Seattle across different neighborhoods.

3 Results

Our analysis of Seattle’s crime rate data from 2020, 2022, and 2024 revealed a notable shift in crime patterns before, during, and after the pandemic. To better understand these trends, we first conducted a descriptive statistical summary of key variables, including crime type, time of occurrence, and location. For categorical variables, such as crime type, we generated a bar chart to visualize the frequency distribution of different offenses. Generally as the years went on, the crime rates throughout Seattle went down. This type of finding has been shown not just in our data, but also in articles like “Changes in Crime Rates during the COVID-19 Pandemic” by Mikaela Meyera , Ahmed Hassafyb,c , Gina Lewisb,d , Prasun Shrestha b,e , Amelia M. Haviland b , and Daniel S. Nagin b. However when comparing crime types, we observed that property crimes like robbery and burglary had initially shown a decline in 2020, likely attributed to increased residential presence during lockdowns, but increased in 2024, which is shown in our bar graphs.

After downloading our data, updating the API keys, we needed to do some data clean up with our two datasets.

Sort was managed/edited mostly by: Francisco Trujillo & Kamila Lopez-Avendano

Sort <- SPD %>%
  select(
    arrest_occurred_date_time,
    arrest_reported_date_time,
    arrest_type,
    cad_clearance,
    cad_initial_call_type,
    cad_priority,
    nibrs_description,
    offense_type,
    officer_age,
    officer_gender,
    officer_race,
    inv_officer_title,
    precinct,
    subject_age_range,
    subject_gender,
    subject_race,
    latitude,
    longitude,
    neighborhood
  )

Sort$arrest_reported_date_time <- as.Date(Sort$arrest_reported_date_time)

#Removing unwanted variables
Sort <- Sort[!(Sort$nibrs_description %in% c("-")) ,]

# Filter for entries for 2020,2022,2024
# General use for all maps
Sort <- filter(Sort, format(arrest_reported_date_time, "%Y" ) %in% c("2020", "2022", "2024")) %>%
  mutate(
    longitude = as.numeric(longitude),
    latitude = as.numeric(latitude)
  ) %>%
  filter(!is.na(longitude) & !is.na(latitude))

offense_reports <- offense_reports %>%
  mutate(year = year(ymd_hms(incident_datetime))) %>%
  filter(year %in% c(2020, 2022, 2024), city == "SEATTLE")  #keep only selected years
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `year = year(ymd_hms(incident_datetime))`.
## Caused by warning:
## !  12932 failed to parse.
## Sort for 2020
Sort_2020 <- Sort %>% filter(format(arrest_reported_date_time, "%Y") == "2020")

## Sort for 2024
Sort_2024 <- Sort[Sort$arrest_reported_date_time > "2024-01-01" & Sort$arrest_reported_date_time < "2024-12-31",]

## Sort for 2022
Sort_2022 <- Sort %>% filter(format(arrest_reported_date_time, "%Y") == "2022")

3.1 2020 Map

Map made by: Christina Scott

# Creating an interactive geo heatmap 
leaflet(Sort_2020) %>%
  addTiles() %>%
  addProviderTiles(provider = "OpenStreetMap") %>%
  setView(-122.339317, 47.586904, 11) %>%
  addHeatmap(lng = ~longitude, lat = ~latitude, intensity = 1,
             blur = 20, radius = 15) %>%
  addControl(html = "<h3>Crime Rates in Seattle During 2020</h3>", 
             position = "topright") %>%  # Correctly chaining addControl()
  addControl(html = "<p style='font-size:7px; background-color: rgba(255, 255, 255, 0.7); padding: 2px;'>
                      Source: Seattle Police Department</p>", 
             position = "bottomright")  # Correctly chaining addControl()

3.2 2022 Maps

The first 2022 map shows arrest occurrences through color, the more crimes committed in the location, the denser the area is.

Map by: Kamila Lopez-Avendano

seattle_map <- get_map(location = "Seattle, WA", zoom = 12, source = "google", maptype = "terrain")
## ℹ <https://maps.googleapis.com/maps/api/staticmap?center=Seattle,%20WA&zoom=12&size=640x640&scale=2&maptype=terrain&language=en-EN&key=xxx-SFbSGGw>
## ℹ <https://maps.googleapis.com/maps/api/geocode/json?address=Seattle,+WA&key=xxx-SFbSGGw>
# Converting data into an sf object
Sort_2022_sf <- Sort_2022 %>%
  st_as_sf(coords = c("longitude", "latitude"), crs = 4326, remove = FALSE)

ggmap(seattle_map) +
  geom_sf(data = Sort_2022_sf, shape = 21, size = 0.1, color = "red", alpha = 0.25, inherit.aes = FALSE) +
  labs(
    title = "Crime Data in Seattle (2022)",
    subtitle = "Crime Arrests occurrences in Seattle in 2022",
    caption = "Data from Seattle Police Department, SPD Arrest Data."
  ) +
  theme_void() +
  theme(    
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
    plot.subtitle = element_text(size = 14, hjust = 0.5),
    plot.caption = element_text(size = 10, hjust = 1),
    plot.background = element_blank(),
    panel.background = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.border = element_blank(),
    legend.position = "none"
    )
## Coordinate system already present. Adding new coordinate system, which will
## replace the existing one.

This second map showcases in an interactive setting, you can find out what crimes happened where in 2022 by zooming and clicking at each dot.

Map by: Kamila Lopez-Avendano

leaflet(Sort_2022) %>%
  addProviderTiles(providers$CartoDB.Positron) %>% 
  setView(lng = -122.3321, lat = 47.6062, zoom = 12) %>%
  
  addCircleMarkers(
    lng = ~longitude,
    lat = ~latitude,
    clusterOptions = markerClusterOptions(),
    radius = 5,
    fillOpacity = 0.7,
    popup = ~paste0(
      "<b>Arrest Date:</b> ", arrest_reported_date_time, 
      "<br><b>Offense:</b> ", offense_type, 
      "<br><b>Location:</b> ", neighborhood,
      "<br><b>Reported Date:</b> ", format(arrest_reported_date_time, "%B %d, %Y")
    )
  ) %>%
  
  addScaleBar(position = "bottomleft") %>%
  
  addLegend(
    position = "bottomright", 
    colors = c("blue"),
    labels = c("Offenses in 2022"),
    title = "Incident Markers"
  )

3.3 2024 Map

Map by: Francisco Trujillo

  leaflet(Sort_2024) %>%
  addTiles() %>%
  addProviderTiles(provider = "OpenStreetMap") %>%
  setView(-122.339317, 47.586904, 11) %>%
  
  addHeatmap(lng =~longitude, lat =~ latitude, blur = 5, radius = 15) %>%
  
  addControl(
    position = "topright",
    html = tags$div(
      style = "font-size: 15px; font-weight: bold; padding: 5px; background-color: rgba(255, 255, 255, 0.7);",
      "Seattle Crime in 2024"
    )
  ) %>%
  # Add a source
  addControl(
    position = "bottomright",
    html = tags$div(
      style = "font-size: 7px; padding: 5px; background-color: rgba(255, 255, 255, 0.7);",
      "Source: SPD"
    )
  )

3.4 Graphs

All graphs by: Huan Yen Wu

crime_counts_hour <- offense_reports %>%
  group_by(year, hour_of_day) %>%
  summarise(incident_count = n(), .groups = 'drop')

ggplot(crime_counts_hour, aes(x = hour_of_day, y = incident_count, color = factor(year))) +
  geom_point(size = 3, alpha = 0.7) +
  geom_line() +
  labs(title = "Crime Trends by Hour in Seattle (2020, 2022, 2024)",
       x = "Hour of the Day", y = "Number of Incidents", color = "Year",
       caption = "Data Source: King County Open Data") +
  theme_minimal() 

crime_counts <- offense_reports %>%
  group_by(year, zip) %>%
  summarise(incident_count = n(), .groups = 'drop')

ggplot(crime_counts, aes(x = zip, y = incident_count, color = factor(year))) +
  geom_jitter(alpha = 0.7, size = 3) +  # Jitter for better spacing
  scale_color_manual(values = c("blue", "red", "green")) +  # Distinct colors
  labs(title = "Crime Reports by Zip Code in Seattle (2020, 2022, 2024)",
       x = "Zip Code", y = "Number of Incidents", color = "Year",
       caption = "Data Source: King County Open Data") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))  # Better label readability

crime_types <- offense_reports %>%
  group_by(year, nibrs_code_name) %>%
  summarise(incident_count = n(), .groups = 'drop') %>%
  arrange(year, desc(incident_count)) %>%
  group_by(year) %>%
  slice_head(n = 10)  # Get top 10 crimes for EACH year

ggplot(crime_types, aes(x = reorder(nibrs_code_name, incident_count), y = incident_count, fill = factor(year))) +
  geom_col(position = "dodge") +
  coord_flip() +
  labs(title = "Top 10 Most Reported Crimes in Seattle (2020, 2022, 2024)",
       x = "Crime Type", y = "Number of Reports", fill = "Year",
       caption = "Data Source: King County Open Data") +
  theme_minimal()

4 Discussion

This data highlights a few things regarding our handling of the pandemic: crime arrests were very high during 2022. According to SPD 2022 Crime Report, citywide crime increased by 4%. In a larger scope, 2024 was a safer year than any of the years according to the SPDs crime dashboard.

A lot of our work had to do with wrangling and cleaning up the data for our use, things like correctly formating the lat/long, API limits, and incorrect datasets caused us to focus less on our visualizations.

We had large limitations with our data, our goal and plan was to use SPD Crime Data: 2008 - Present (https://data.seattle.gov/Public-Safety/SPD-Crime-Data-2008-Present/tazs-3rd5/about_data), but we had several problems. First, the dataset was huge, there was 1.44M rows for it’s 19 columns. This was fixed by re-working the API code. Second, and what was our breaking point was even though there was columns for latitude and longitude, they didn’t contain any data, they were all null values. We switched over the Arrest Data because while it didn’t exactly say what we wanted, it still contained the data we needed.

One of our group members had an older laptop that could not handle API keys, which caused us great problems while creating/loading the maps.