library(pacman)
p_load(here, tidyverse, zoo, lubridate, ggplot2, plotly, gghighlight, sf, tigris, ggrepel, viridis)
options(scipen = 1000000)
specific_aor <- params$aor
# ENCOUNTERS DATA
enc <- read_delim(here('write', 'input', 'ice_encounters_fy12-23ytd.csv.gz'), delim='|',
col_types = cols(aor = col_factor(),
event_date = col_character(),
landmark = col_character(),
operation = col_factor(),
processing_disposition = col_factor(),
citizenship_country = col_factor(),
gender = col_factor(),
hashid = col_character(),
id = col_number()))
# glimpse(enc)
redacted <- c('encounter_threat_level', 'alien_file_number')
enc <- enc %>%
dplyr::select(-redacted)
enc <- enc %>%
mutate(aor = factor(aor, levels = sort(levels(enc$aor))),
event_date = as_date(event_date, format="%m/%d/%Y"),
year = year(event_date),
month = month(event_date, label=TRUE, abbr=TRUE),
year_mth = zoo::as.yearmon(event_date),
fy_quarter = as.factor(quarter(event_date, fiscal_start=10, type="year.quarter")),
fy = as.factor(substr(fy_quarter, 1,4)),
gender = as.factor(toupper(gender)),
operation = toupper(operation),
processing_disposition = toupper(processing_disposition),
citizenship_country = toupper(citizenship_country),
landmark = toupper(str_squish(landmark))) %>%
filter(event_date >= "2011-10-01",
event_date <= "2022-09-30")
# ARRESTS DATA
arr <- read_delim(here('write', 'input', 'ice_arrests_fy12-23ytd.csv.gz'), delim='|',
col_types = cols(aor = col_factor(),
arrest_date = col_date(format="%m/%d/%Y"),
departed_date = col_date(format="%m/%d/%Y"),
apprehension_landmark = col_factor(),
arrest_method = col_factor(),
operation = col_factor(),
processing_disposition = col_factor(),
citizenship_country = col_factor(),
gender = col_factor(),
case_closed_date = col_date(format="%m/%d/%Y"),
id = col_integer(),
hashid = col_character()
))
redacted <- c('removal_threat_level', 'apprehension_threat_level', 'alien_file_number')
arr <- arr %>%
dplyr::select(-all_of(redacted))
arr <- arr %>%
mutate(aor = factor(aor, levels = sort(levels(arr$aor))),
arrest_date = as_date(arrest_date, format="%m/%d/%Y"),
year = year(arrest_date),
month = month(arrest_date, label=TRUE, abbr=TRUE),
year_mth = zoo::as.yearmon(arrest_date),
fy_quarter = as.factor(quarter(arrest_date, fiscal_start=10, type="year.quarter")),
fy = as.factor(substr(fy_quarter, 1,4)),
gender = as.factor(toupper(gender)),
citizenship_country = as.factor(toupper(citizenship_country)),
apprehension_landmark = toupper(str_squish(apprehension_landmark))) %>%
filter(arrest_date >= "2011-10-01",
arrest_date <= "2022-09-30")
# REMOVALS DATA
pd_dict <- read_delim(here('share', 'hand', 'processing_disp.csv'), delim='|')
rem <- read_delim(here('write', 'input', 'ice_removals_fy12-23ytd.csv.gz'), delim='|',
col_types = cols(aor = col_factor(),
arrest_date = col_date(format="%m/%d/%Y"),
departed_date = col_date(format="%m/%d/%Y"),
case_close_date = col_date(format="%m/%d/%Y"),
removal_date = col_date(format="%m/%d/%Y"),
apprehension_method_code = col_character(),
processing_disposition_code = col_factor(),
citizenship_country = col_factor(),
gender = col_factor(),
final_charge_section = col_factor(),
id = col_integer(),
hashid = col_character()
))
redacted <- c('removal_threat_level', 'alien_file_number')
rem <- rem %>%
dplyr::select(-redacted, -case_closed_date)
rem <- rem %>%
mutate(aor = factor(aor, levels = sort(levels(rem$aor))),
year = year(departed_date),
month = month(departed_date, label=TRUE, abbr=TRUE),
year_mth = zoo::as.yearmon(departed_date),
processing_disp = toupper(coalesce(processing_disposition_code, processing_disposition)),
fy_quarter = as.factor(quarter(departed_date, fiscal_start=10, type="year.quarter")),
fy = as.factor(substr(fy_quarter, 1,4)),
gender = as.factor(toupper(gender)),
citizenship_country = toupper(citizenship_country)) %>%
filter(departed_date >= "2011-10-01",
departed_date <= "2022-09-30")
rem <- left_join(rem, pd_dict, by=c('processing_disp' = 'processing_disposition_raw'))
# SUPPLEMENTAL DATA
demog <- read_delim(here('share', 'input', 'aor_demog_indicators.csv'), delim='|') %>%
arrange(aor, year) %>%
mutate(year = as.factor(year))
pc_scale = 100000
# Should get this from an external constants file along with other AOR characteristics
specific_area_of_responsibility <- arr %>%
filter(aor == specific_aor) %>%
distinct(area_of_responsibility) %>%
as.character()
This notebook provides a basic descriptive overview of ICE ERO-LESA enforcement data for the Denver Area of Responsibility (DEN) for the time period from October 1, 2011, through January 29, 2023, (full U.S. Government Fiscal Years 2012 through 2022), obtained by the University of Washington Center for Human Rights (UWCHR) pursuant to FOIA request 2022-ICFO-09023.
For data and code used to generate this notebook, see: https://github.com/UWCHR/ice-enforce
enc_fy <- enc %>%
filter(aor == specific_aor) %>%
group_by(fy) %>%
summarize(n_encounters = n())
arr_fy <- arr %>%
filter(aor == specific_aor) %>%
group_by(fy) %>%
summarize(n_arrests = n())
rem_fy <- rem %>%
filter(aor == specific_aor) %>%
group_by(fy) %>%
summarize(n_removals = n())
dat_aor <- left_join(enc_fy, arr_fy, by='fy') %>%
left_join(rem_fy, by='fy')
p1 <- dat_aor %>%
pivot_longer(cols=-c('fy')) %>%
ggplot(aes(x = fy, y=value, color=name, group=name)) +
geom_line() +
ylim(0, NA) +
labs(title = paste0("Total ICE enforcement events per FY",
'<br>',
'<sup>',
specific_area_of_responsibility,
'</sup>'),
caption = "Figure: Univ. of Wash. Center for Human Rights, Data: ICE ERO-LESA",
x = "Fiscal Year",
y = "") +
guides(color = guide_legend("Enforcement type")) +
theme_minimal()
ggplotly(p1)
The following chart displays basic comparative measures for the
Denver Area of Responsibility: difference between total encounters and
total arrests (diff_enc_arr); and difference between total
removals and total arrests (diff_rem_arr). Values greater
than zero denote periods in which there were either more encounters than
arrests, or more removals than arrests, respectively.
dat_diff <- dat_aor %>%
mutate(diff_enc_arr = n_encounters - n_arrests,
diff_rem_arr = n_removals - n_arrests)
p2 <- dat_diff %>%
pivot_longer(cols=-c('fy')) %>%
filter(name %in% c("diff_enc_arr", "diff_rem_arr")) %>%
ggplot(aes(x = fy, y=value, color=name, group=name)) +
geom_line() +
geom_hline(aes(yintercept=0),
linetype="dashed",
linewidth=.25) +
# annotate("text", x = 2, y = 0, label = "Fewer arrests\nMore arrests") +
labs(title = paste0("Difference of enforcement event totals per FY",
'<br>',
'<sup>',
specific_area_of_responsibility,
'</sup>'),
x = "Fiscal Year",
y = "") +
theme_minimal()
ggplotly(p2)
Here we compare trends for the Denver Area of Responsibility with national trends:
enc_fy_natl <- enc %>%
filter(
event_date <= "2022-09-30") %>%
group_by(fy) %>%
summarize(n_encounters = n())
arr_fy_natl <- arr %>%
filter(
arrest_date <= "2022-09-30") %>%
group_by(fy) %>%
summarize(n_arrests = n())
rem_fy_natl <- rem %>%
filter(
departed_date <= "2022-09-30") %>%
group_by(fy) %>%
summarize(n_removals = n())
dat_natl <- left_join(enc_fy_natl, arr_fy_natl, by='fy') %>%
left_join(rem_fy_natl, by='fy')
dat_aor$group <- specific_area_of_responsibility
dat_natl$group <- "National total"
dat <- rbind(dat_aor, dat_natl)
p1 <- dat %>%
rename(encounters = n_encounters,
arrests = n_arrests,
removals = n_removals) %>%
pivot_longer(cols=-c('fy', 'group')) %>%
ggplot(aes(x = fy, y=value, color=name, group=name, text=group)) +
geom_line() +
labs(title = "Total ICE enforcement events, FY2012-22") +
xlab('Fiscal Year') +
scale_x_discrete(breaks=as.character(seq(2013,2024,4))) +
ylab("") +
ylim(0, NA) +
scale_color_discrete(name = "Enforcement type") +
facet_wrap(~group, scales = "free_y") +
theme_minimal()
ggplotly(p1, tooltip = c("x", "y", "color", "text"))
Annual percent change in enforcement actions per FY, Denver Area of Responsibility compared to national.
dat_pct <- dat %>%
group_by(group) %>%
mutate(across(starts_with('n_'), ~ (.x/lag(.x) - 1))) %>%
pivot_longer(cols = c(-fy, -group))
p3 <- dat_pct %>%
filter(!is.na(value)) %>%
ggplot(aes(x = fy, y = value, fill=name, group=name)) +
geom_col(position='dodge') +
scale_y_continuous(labels = scales::percent) +
scale_x_discrete(breaks=seq(2013,2024,4)) +
facet_wrap(~group) +
labs(title = "Annual % change total ICE enforcement actions, FY12-22") +
theme_minimal()
ggplotly(p3)
For national overview, see the Encounters notebook.
enc_per_aor <- enc %>%
filter(!is.na(aor),
aor != "HQ",
event_date <= "2022-09-30") %>%
group_by(fy, aor) %>%
summarize(n = n())
enc_pc_per_aor <- left_join(enc_per_aor, demog, by=c('fy' = 'year', 'aor' = 'aor')) %>%
group_by(aor) %>%
fill(contains('pop')) %>%
mutate(n_per_cap = (n / total_pop) * pc_scale,
n_per_undocu = (n / undocu_pop) * pc_scale) %>%
arrange(fy, desc(n_per_cap)) %>%
group_by(fy) %>%
mutate(pc_rank = row_number())
pc_encounter_rank_fy12 <- as.numeric(enc_pc_per_aor[enc_pc_per_aor$aor == specific_aor & enc_pc_per_aor$fy == 2012, 'pc_rank'])
pc_encounter_rank_fy22 <- as.numeric(enc_pc_per_aor[enc_pc_per_aor$aor == specific_aor & enc_pc_per_aor$fy == 2022, 'pc_rank'])
p1 <- enc_pc_per_aor %>%
ggplot(aes(x = fy, y=n_per_cap, color=aor, group=aor)) +
geom_line() +
gghighlight(aor == specific_aor, use_direct_label = FALSE) +
xlab("Fiscal Year") +
ylab("Encounters per capita") +
labs(title = "ICE encounters per 100,000 residents",
subtitle = paste0(specific_area_of_responsibility, " highlighted")) +
theme_minimal()
p1
genderp1 <- enc %>%
filter(aor == specific_aor) %>%
count(fy, gender) %>%
ggplot(aes(x=fy, y=n, fill=gender)) +
geom_col(position='fill') +
scale_y_continuous(labels = scales::percent) +
ylab("") +
xlab('Fiscal Year') +
labs(title="ICE encounters, % by gender",
subtitle=specific_area_of_responsibility) +
theme_minimal()
p1
citizenship_countrycit <- enc %>%
filter(aor == specific_aor) %>%
mutate(citizenship_country = toupper(citizenship_country)) %>%
group_by(citizenship_country) %>%
summarize(n = n()) %>%
arrange(desc(n))
p1 <- enc %>%
filter(aor == specific_aor) %>%
mutate(citizenship_country = case_when(
citizenship_country %in% head(cit$citizenship_country, 15) ~ citizenship_country,
TRUE ~ "ALL OTHERS"
)) %>%
count(fy, citizenship_country) %>%
ggplot(aes(x=fy, y=n, fill=citizenship_country, color=citizenship_country)) +
geom_col() +
labs(title = paste0("ICE encounters by country of citizenship (top 15)",
'<br>',
'<sup>',
specific_area_of_responsibility,
'</sup>')) +
theme_minimal()
ggplotly(p1)
p2 <- enc %>%
filter(aor == specific_aor) %>%
mutate(citizenship_country = case_when(
citizenship_country %in% head(cit$citizenship_country, 15) ~ citizenship_country,
TRUE ~ "ALL OTHERS"
)) %>%
count(fy, citizenship_country) %>%
ggplot(aes(x=fy, y=n, fill=citizenship_country, color=citizenship_country)) +
scale_y_continuous(labels = scales::percent) +
geom_col(position = "fill") +
labs(title = paste0("ICE encounters by country of citizenship (top 15)",
'<br>',
'<sup>',
specific_area_of_responsibility,
'</sup>')) +
theme_minimal()
ggplotly(p2)
landmarkFor more on landmark values, see the Landmarks notebook.
landmarks <- enc %>%
filter(aor == specific_aor) %>%
count(landmark) %>%
arrange(desc(n))
p1 <- enc %>%
filter(aor == specific_aor) %>%
mutate(landmark = case_when(landmark %in% head(landmarks$landmark, 15) ~ as.character(landmark),
TRUE ~ "ALL OTHERS"),
landmark_abbrv = str_trunc(landmark, 20)) %>%
group_by(fy, landmark_abbrv, landmark) %>%
summarize(n = n()) %>%
ggplot(aes(x = fy, y=n,
fill=landmark_abbrv,
color=landmark_abbrv,
text = landmark)) +
geom_col() +
labs(title = paste0("Total ICE encounters per FY by `landmark` (top 15)",
'<br>',
'<sup>',
specific_area_of_responsibility,
'</sup>')) +
theme_minimal()
ggplotly(p1, tooltip=c('x', 'y', 'text'))
operationops <- enc %>%
filter(aor == specific_aor) %>%
count(operation) %>%
arrange(desc(n))
p1 <- enc %>%
filter(aor == specific_aor) %>%
mutate(operation_short = case_when(operation %in% head(ops$operation, 10) ~ as.character(operation),
TRUE ~ "ALL OTHERS")) %>%
group_by(fy, operation_short) %>%
summarize(n = n()) %>%
ggplot(aes(x = fy, y=n, fill=operation_short)) +
geom_col() +
labs(title = "Total ICE encounters per FY by operation") +
theme_minimal()
ggplotly(p1)
processing_dispositionaor_disps <- enc %>%
filter(aor == specific_aor) %>%
count(processing_disposition) %>%
arrange(desc(n))
p1 <- enc %>%
filter(aor == specific_aor) %>%
mutate(disp_short = case_when(processing_disposition %in% head(aor_disps$processing_disposition, 10) ~ as.character(processing_disposition),
TRUE ~ "ALL OTHERS")) %>%
group_by(fy, disp_short) %>%
summarize(n = n()) %>%
ggplot(aes(x = fy, y=n, fill=disp_short, color=disp_short)) +
geom_col() +
labs(title = paste0("Total ICE encounters per FY by `processing disposition` (top 15)",
'<br>',
'<sup>',
specific_area_of_responsibility,
'</sup>')) +
theme_minimal()
ggplotly(p1, dynamicTicks = TRUE)
For national overview, see the Arrests notebook.
arr_per_aor <- arr %>%
filter(!is.na(aor),
aor != "HQ",
arrest_date <= "2022-09-30") %>%
group_by(fy, aor) %>%
summarize(n = n())
arr_pc_per_aor <- left_join(arr_per_aor, demog, by=c('fy' = 'year', 'aor' = 'aor')) %>%
group_by(aor) %>%
fill(contains('pop')) %>%
mutate(n_per_cap = (n / total_pop) * pc_scale,
n_per_undocu = (n / undocu_pop) * pc_scale) %>%
arrange(fy, desc(n_per_cap)) %>%
group_by(fy) %>%
mutate(pc_rank = row_number())
p1 <- arr_pc_per_aor %>%
ggplot(aes(x = fy, y=n_per_cap, color=aor, group=aor)) +
geom_line() +
gghighlight(aor == specific_aor, use_direct_label = FALSE) +
labs(title = "ICE arrests per 100,000 residents",
subtitle = paste0(specific_area_of_responsibility, " highlighted")) +
theme_minimal()
p1