This map shows the number of law enforcement agencies in California that report crime data to the FBI’s National Incident-Based Reporting System (NIBRS).
Figure 1: This map was created using ggplot2, cowplot, and other R packages to visualize California’s county-level NIBRS participation. The FBI Crime Data was processed by filtering for California, wrangling the data to extract agency counts and proportions, and then joining it with county map data, resulting in 73.7% of agencies reporting to NIBRS, while 26.3% do not. This analysis highlights the extent of NIBRS participation across California, offering a clearer picture of crime data reporting at the county level.
How This Graphic Was Made
1. 📦 Load Packages & Setup
Show code
# Load necessary packages using pacman for easier dependency managementpacman::p_load(tidyverse, # Collection of R packages for data science, includes ggplot2 (visualization), dplyr (data manipulation), readr (data import)showtext, # Enables custom fonts in ggplot2, allowing for enhanced typography in plotsggtext, # Adds support for Markdown and HTML formatting in ggplot2 text elements (e.g., bold, italic, colored text)skimr, # Provides detailed summary statistics in a readable and concise format for data explorationglue, # Constructs strings efficiently using variable interpolationjanitor, # Simplifies data cleaning (e.g., renaming columns, removing duplicates, formatting variable names)paletteer, # Provides access to a wide range of color palettes for consistent and visually appealing plotscowplot# Enhances ggplot2 with better layout and annotation options, useful for combining multiple plots)# Add Google fontsfont_add_google("Oswald", family ="Oswald")font<-"Oswald"# Add local fontfont_add("Font Awesome 6 Brands", here::here("fonts/otfs/Font Awesome 6 Brands-Regular-400.otf"))# Automatically enable the use of showtext for all plotsshowtext_auto()# Set DPI for high-resolution text renderingshowtext_opts(dpi =300)
2. 📖 Read in the Data
Show code
# Load the TidyTuesday dataset for Week 07 of 2025tuesdata<-tidytuesdayR::tt_load(2025, week =07)# Extract and clean column names in the agencies datasetagencies<-tuesdata$agencies%>%clean_names()# Display dataset information from TidyTuesdaytidytuesdayR::readme(tuesdata)# Remove the original loaded list to free memoryrm(tuesdata)
3. 🕵️ Examine the Data
Show code
# Display the structure of the agencies dataset, including column types and sample valuesglimpse(agencies)# Generate a detailed summary of the agencies dataset, including distribution and missing valuesskim(agencies)
4. 🤼 Wrangle Data
Show code
# Get California county map dataca_counties<-subset(map_data("county"), region=="california")# Filter agencies for California and format county namescalifornia<-agencies%>%filter(state_abbr=="CA")%>%mutate(county =str_to_lower(county))%>%group_by(county, is_nibrs)%>%count(is_nibrs)%>%ungroup()# Calculate the percentage of agencies reporting to NIBRS in Californiaperc<-california%>%group_by(is_nibrs)%>%summarise(count =sum(n))%>%mutate(proportion =round(count/sum(count)*100, 1))%>%ungroup()%>%pull(proportion)# Merge California county map data with agency datacalifornia<-ca_counties%>%left_join(california, by =join_by(subregion==county))# Extract data for Los Angeles Countylos_angeles<-california%>%filter(subregion=="los angeles")
5. 🔤 Text
Show code
# Define the main title for the visualizationtitle<-"California Agencies on the FBI’s\nNational Incident-Based Reporting System (NIBRS)"# Create a short description of the dataset focusst<-"The FBI Crime Data Explorer provides access to crime data from\nlaw enforcement agencies nationwide. This dataset focuses on California agencies\nthat report through the National Incident-Based Reporting System (NIBRS)."# Highlight key insight about agency participation in Los Angeles Countytext<-"Los Angeles County has the highest number\nof agencies participating in NIBRS, with a total of 61."# Generate the formatted textcal_perc<-glue("In California, {perc[2]}% of agencies report to NIBRS, while {perc[1]}% do not.")# Generate a social media caption with custom colors and font stylingsocial<-andresutils::social_caption(font_family =font, icon_color ="#b2d8ee", bg_color ="gray10", font_color ="white")# Construct the final plot caption with TidyTuesday details, data source, and social captioncap<-paste0("#TidyTuesday: Week 07, 2025 | **Source**: FBI Crime Data API | **Graphic**: ", social)
6. 📊 Plot
Show code
# Create a base map of California showing NIBRS-participating agenciesp<-california%>%filter(is_nibrs=="TRUE")%>%ggplot()+geom_polygon(aes(x =long, y =lat, group =group, fill =n), color ="gray50")+geom_polygon(data =los_angeles, aes(x =long, y =lat, group =group), color ="#EFBF04", fill =NA, size =1.5)+scale_fill_paletteer_c("ggthemes::Blue")+labs(caption =cap)+theme_void()+theme( legend.position =c(0.15, 0.2), legend.key.width =unit(1.2, "cm"), legend.key.height =unit(1.8, "cm"), legend.title =element_blank(), legend.text =element_text(color="white", size =22, family =font, face ="bold"), plot.background =element_rect(fill ="gray10", color ="transparent"), plot.caption =element_textbox_simple(color ="white", family =font, size =10))# Add text, labels, and annotations to the mapp1<-ggdraw(p)+draw_text(text =title, x =0.72, y =0.9, size =20, color ="white", family =font, fontface ="bold")+draw_text(text ="Number of Agencies", color ="white", x =0.09, y =0.2, size =21, family =font, fontface ="bold", angle =90)+draw_text(text =text, x =0.43, y =0.12, color ="white", family =font)+annotate("curve", x =0.45, y =0.14, xend =0.57, yend =0.21, color ="white", curvature =-0.2, linewidth =0.7, arrow =arrow(length =unit(0.4, 'cm')))+draw_text(text =st, x =0.72, y =0.82, color ="white", family =font)+draw_text(text =cal_perc, x=0.68, y =0.5, color ="white", family =font, angle =-45, size =18)
7. 💾 Save
Show code
# Save the plot for TidyTuesday 2025, Week 07 with specified dimensions.andresutils::save_plot(p1, type ="tidytuesday", year =2025, week =7, width =11, height =14)
8. 🚀 GitHub Repository
Expand for GitHub Repo
The complete code for this analysis is available in tt_07_2025.qmd.
Do you enjoy my blog? Subscribe here to get notifications and updates (it's free!):
Source Code
---title: "Agencies from the FBI Crime Data"description: "This map shows the number of law enforcement agencies in California that report crime data to the FBI’s National Incident-Based Reporting System (NIBRS)."lightbox: truedate: February 20, 2025categories: [TidyTuesday, R Programming, Data Visualization, Crime Data]tags: [ggplot2, data-visualization, tidyverse, Crime Data]image: "tt_07_2025.png"editor_options: chunk_output_type: inline---{#fig-1}### <mark> **How This Graphic Was Made** </mark>#### 1. 📦 Load Packages & Setup```{r}#| label: load#| warning: false#| message: false#| results: hide# Load necessary packages using pacman for easier dependency managementpacman::p_load( tidyverse, # Collection of R packages for data science, includes ggplot2 (visualization), dplyr (data manipulation), readr (data import) showtext, # Enables custom fonts in ggplot2, allowing for enhanced typography in plots ggtext, # Adds support for Markdown and HTML formatting in ggplot2 text elements (e.g., bold, italic, colored text) skimr, # Provides detailed summary statistics in a readable and concise format for data exploration glue, # Constructs strings efficiently using variable interpolation janitor, # Simplifies data cleaning (e.g., renaming columns, removing duplicates, formatting variable names) paletteer, # Provides access to a wide range of color palettes for consistent and visually appealing plots cowplot # Enhances ggplot2 with better layout and annotation options, useful for combining multiple plots)# Add Google fontsfont_add_google("Oswald", family ="Oswald")font <-"Oswald"# Add local fontfont_add("Font Awesome 6 Brands", here::here("fonts/otfs/Font Awesome 6 Brands-Regular-400.otf"))# Automatically enable the use of showtext for all plotsshowtext_auto()# Set DPI for high-resolution text renderingshowtext_opts(dpi =300)```#### 2. 📖 Read in the Data```{r}#| label: read#| include: true#| eval: true#| warning: false# Load the TidyTuesday dataset for Week 07 of 2025tuesdata <- tidytuesdayR::tt_load(2025, week =07)# Extract and clean column names in the agencies datasetagencies <- tuesdata$agencies %>%clean_names()# Display dataset information from TidyTuesdaytidytuesdayR::readme(tuesdata)# Remove the original loaded list to free memoryrm(tuesdata)```#### 3. 🕵️ Examine the Data```{r}#| label: examine#| include: true#| eval: true#| results: hide#| warning: false# Display the structure of the agencies dataset, including column types and sample valuesglimpse(agencies)# Generate a detailed summary of the agencies dataset, including distribution and missing valuesskim(agencies)```#### 4. 🤼 Wrangle Data```{r}#| label: wrangle#| warning: false# Get California county map dataca_counties <-subset(map_data("county"), region =="california")# Filter agencies for California and format county namescalifornia <- agencies %>%filter(state_abbr =="CA") %>%mutate(county =str_to_lower(county)) %>%group_by(county, is_nibrs) %>%count(is_nibrs) %>%ungroup()# Calculate the percentage of agencies reporting to NIBRS in Californiaperc <- california %>%group_by(is_nibrs) %>%summarise(count =sum(n)) %>%mutate(proportion =round(count /sum(count) *100, 1)) %>%ungroup() %>%pull(proportion)# Merge California county map data with agency datacalifornia <- ca_counties %>%left_join(california, by =join_by(subregion == county))# Extract data for Los Angeles Countylos_angeles <- california %>%filter(subregion =="los angeles")```#### 5. 🔤 Text```{r}#| label: text#| include: true#| warning: false# Define the main title for the visualizationtitle <-"California Agencies on the FBI’s\nNational Incident-Based Reporting System (NIBRS)"# Create a short description of the dataset focusst <-"The FBI Crime Data Explorer provides access to crime data from\nlaw enforcement agencies nationwide. This dataset focuses on California agencies\nthat report through the National Incident-Based Reporting System (NIBRS)."# Highlight key insight about agency participation in Los Angeles Countytext <-"Los Angeles County has the highest number\nof agencies participating in NIBRS, with a total of 61."# Generate the formatted textcal_perc <-glue("In California, {perc[2]}% of agencies report to NIBRS, while {perc[1]}% do not.")# Generate a social media caption with custom colors and font stylingsocial <- andresutils::social_caption(font_family = font, icon_color ="#b2d8ee", bg_color ="gray10", font_color ="white") # Construct the final plot caption with TidyTuesday details, data source, and social captioncap <-paste0("#TidyTuesday: Week 07, 2025 | **Source**: FBI Crime Data API | **Graphic**: ", social)```#### 6. 📊 Plot```{r}#| label: plot#| warning: false# Create a base map of California showing NIBRS-participating agenciesp <- california %>%filter(is_nibrs =="TRUE") %>%ggplot() +geom_polygon(aes(x = long, y = lat, group = group, fill = n), color ="gray50") +geom_polygon(data = los_angeles, aes(x = long, y = lat, group = group), color ="#EFBF04", fill =NA, size =1.5) +scale_fill_paletteer_c("ggthemes::Blue") +labs(caption = cap) +theme_void() +theme(legend.position =c(0.15, 0.2),legend.key.width =unit(1.2, "cm"),legend.key.height =unit(1.8, "cm"),legend.title =element_blank(),legend.text =element_text(color="white", size =22, family = font, face ="bold"),plot.background =element_rect(fill ="gray10", color ="transparent"),plot.caption =element_textbox_simple(color ="white", family = font, size =10) )# Add text, labels, and annotations to the mapp1 <-ggdraw(p) +draw_text(text = title, x =0.72, y =0.9, size =20, color ="white", family = font, fontface ="bold") +draw_text(text ="Number of Agencies", color ="white", x =0.09, y =0.2, size =21, family = font, fontface ="bold", angle =90) +draw_text(text = text, x =0.43, y =0.12, color ="white", family = font) +annotate("curve", x =0.45, y =0.14, xend =0.57, yend =0.21, color ="white", curvature =-0.2, linewidth =0.7, arrow =arrow(length =unit(0.4, 'cm'))) +draw_text(text = st, x =0.72, y =0.82, color ="white", family = font) +draw_text(text = cal_perc, x=0.68, y =0.5, color ="white", family = font, angle =-45, size =18)```#### 7. 💾 Save```{r}#| label: save#| warning: false# Save the plot for TidyTuesday 2025, Week 07 with specified dimensions.andresutils::save_plot(p1, type ="tidytuesday", year =2025, week =7, width =11, height =14)```#### 8. 🚀 GitHub Repository::: {.callout-tip collapse="true"}##### Expand for GitHub RepoThe complete code for this analysis is available in [`tt_07_2025.qmd`](https://github.com/OKcomputer626/Andres-Portfolio/blob/master/visualization/TidyTuesday/2025/Week_07/tt_07_2025.qmd).For the full repository, [click here](https://github.com/OKcomputer626/Andres-Portfolio).:::