── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
Then I upload the datasets that I downloaded and converted from a excel sheet to a CVS document. “Skip” skips the first 6 lines before reading the header. “col_types”
this displays the column names for the years 2023 and 2025 respectively
names(arrests_2023)
[1] "AOR" "County"
[3] "Apprehension Criminality" "Apprehension Date"
[5] "Event Landmark" "Apprehension Method"
[7] "State" "City"
[9] "Birth Year" "Case Category"
[11] "Case Status" "Case Threat Level"
[13] "Citizenship Country" "Departed Date"
[15] "Departure Country" "Final Order Date"
[17] "Final Order Yes No" "Final Program"
[19] "Final Program Group" "Gender"
[21] "Alien File Number" "Anonymized Unique Identifier"
names(arrests_2025)
[1] "AOR" "County"
[3] "Apprehension Criminality" "Apprehension Date"
[5] "Event Landmark" "Apprehension Method"
[7] "State" "City"
[9] "Birth Year" "Case Category"
[11] "Case Status" "Case Threat Level"
[13] "Citizenship Country" "Departed Date"
[15] "Departure Country" "Final Order Date"
[17] "Final Order Yes No" "Final Program"
[19] "Final Program Group" "Gender"
[21] "Alien File Number" "Anonymized Unique Identifier"
These lines assign a fiscal-year label to every row in each dataset. The $ symbol selects a column, and <-assigns its value. If Fiscal_Year does not already exist, these lines create it.
“bind_rows()”combines the data sets vertically. The columns are matched by name. If a column appears in only one dataset, the other dataset’s rows receive missing values in that column. then all that is stored under “arrests_all”
this shows the number of rows assocoiated with each fiscal year
table(arrests_all$Fiscal_Year)
2023 2025
234679 234679
here I displayed the total number of rows in the combined data set as well as adding up the 2 data sets to make sure they were combined properly
nrow(arrests_all)
[1] 469358
nrow(arrests_2023) +nrow(arrests_2025)
[1] 469358
This calls count(), but the quotation marks make treat Apprehension Criminality as text rather than a reference to the column.
count(arrests_all, "Apprehension Criminality")
# A tibble: 1 × 2
`"Apprehension Criminality"` n
<chr> <int>
1 Apprehension Criminality 469358
I use ggplot to make a graph, arrest_all is the data set it uses, aes=aesthetic, which changes the visual features of the graph. x=factor(fiscal year) puts fiscal year as the x axis, as well as treats the years as categories. geom_bar counts the amount of rows and puts them side by side. scale_fill_manual and values first allow you to set specific colors and not use the default ggplot colors. values then allows you to pick the colors using hex numbers. scale_y_continuous formats the y axis with thousands separators. labs formats the graphs titles, including title, subtitle, and x and y titles. theme minimal replaces the original ggplot theme with a minimal design
ggplot( arrests_all,aes(x =factor(Fiscal_Year),fill =`Apprehension Criminality` )) +geom_bar(position ="dodge") +scale_fill_manual(values =c("#2166AC", "#D95F02", "#7570B3") ) +scale_y_continuous(labels = scales::label_comma()) +labs(title ="Recorded Arrests by Fiscal Year and Criminality Category",subtitle ="From FY2023 and FY2025",x ="Fiscal Year",y ="Number of Arrest Records",fill ="Criminality Category",caption ="Source: ERO LESA Statistical Tracking Unit, Hausman ARS files." ) +theme_minimal()
Summary
I prepared the data sets by importing the FY2023 and FY2025 CSV files using the read_csv() function. When I imported the data sets I skipped the first six lines of each file to begin reading at the right column header. I was also careful to make sure that the imported columns use the character data type in order to prevent R from assigning different data types to corresponding columns in the two files.
After importing the files, I checked their column names and added a Fiscal_Year column to identify which year each record belonged to. I then combined the datasets using bind_rows(), which binds them vertically. This matched the columns by name. I wanted to make sure the combined data set was properly binded, so I used nrow twice, one on the combined data set and another time on the first data set + the second data set, in order to make sure the number of records in each fiscal year matched the combined data set
I also explored the data set using a frequency table of fiscal year and criminality category. I included missing values in this table to identify whether any records lacked category information. Then I checked the first six rows using head(). These steps focused on organizing and checking the data.
Visualization and Findings
My intended visualization is a side-by-side bar chart comparing the number of records in each criminality category across both fiscal years. The horizontal axis is the fiscal year, while the vertical axis shows the number of records. I chose Blue, orange, and purple to distinguish the categories, and the legend explains their meanings. The chart also includes a descriptive title, a source caption, and a minimal theme.
convicted criminals were always the top criminality category across both years, with pending criminal charges being second and other immigration violator’s being last
These comparisons describe the records contained in the files. But the chart alone cannot explain why category counts differ.
Limitations/Improvements/Things I wanted to include
One limitation in my code is that geom_bar(position = "dodge") counts the rows in each fiscal year and criminality category. This properly represents the number of arrests only if each row equals one arrest. In order to improve this, I could verify how the data is structured and, if the rows contain summarized totals, use geom_col() , then map those totals to the y-axis.
I wanted to include a percentage-based comparison alongside the record counts. This would help show whether the proportion of records in each category changed, even if the total number of records differed between years.