2020-10-26
The code I use to derive the victim and offender counts can be found below.
library(tidyverse)
library(data.table)
get_crime <- function(x){
data.table::fcase(
##Violent Crimes 1-20
x == 1, "Completed rape",
x == 2, "Attempted rape",
x == 3, "Sexual attack with serious assault",
x == 4, "Sexual attack with minor assault",
x == 5, "Completed robbery with injury from serious assault",
x == 6, "Completed robbery with injury from minor assault",
x == 7, "Completed robbery without injury from minor assault",
x == 8, "Attempted robbery with injury from serious assault",
x == 9, "Attempted robbery with injury from minor assault",
x == 10, "Attempted robbery without injury",
x == 11, "Completed aggravated assault with injury",
x == 12, "Attempted aggravated assault with weapon",
x == 13, "Threatened assault with weapon",
x == 14, "Simple assault completed with injury",
x == 15, "Sexual assault without injury",
x == 16, "Unwanted sexual contact without force",
x == 17, "Assault without weapon without injury",
x == 18, "Verbal threat of rape",
x == 19, "Verbal threat of sexual assault",
x == 20, "Verbal threat of assault",
##Purse snatching/pocket picking 21-23
x == 21, "Completed purse snatching",
x == 22, "Attempted purse snatching",
x == 23, "Pocket picking (completed only)",
##Property Crimes
x == 31, "Completed burglary, forcible entry",
x == 32, "Completed burglary, unlawful entry without force",
x == 33, "Attempted forcible entry",
x == 40, "Completed motor vehicle theft",
x == 41, "Attempted motor vehicle theft",
x == 54, "Completed theft less than $10",
x == 55, "Completed theft $10 to $49",
x == 56, "Completed theft $50 to $249",
x == 57, "Completed theft $250 or greater",
x == 58, "Completed theft value NA",
x == 59, "Attempted theft",
default = NA_character_ )
}
recode_serious_crimes <- function(x){
data.table::fcase(
x %in% 1:4, "Rape/Sexual attack",
x %in% 5:10, "Robbery",
x %in% 11:13, "Assault",
x %in% 14:20, "Minor violent crime",
x %in% 21:23, "Purse snatch/pocket picking",
x %in% 31:59, "Property crimes",
default = NA_character_ )
}
get_race <- function(x){
data.table::fcase(
x == 1, "White",
x == 2, "Black",
x == 3, "American Indian",
x == 4, "Asian",
x == 5, "Hawaiian",
x == 6, "White-Black",
x == 7, "White-American Indian",
x == 8, "White-Asian",
x == 9, "White-Hawaiian",
x == 10, "Black-American Indian",
x == 11, "Black-Asian",
x == 12, "Black-Hawaiian",
x == 13, "American Indian-Asian",
x == 14, "Asian-Hawaiian",
x == 15, "White-Black-American Indian",
x == 16, "White-Black-Asian",
x == 17, "White-American Indian-Asian",
x == 18, "White-Asian-Hawaiian",
x == 19, "2 or 3 races",
x == 20, "4 or 5 races",
default = NA_character_)
}
get_race_category <- function(race, hisp){
data.table::fcase(
race %chin% c("White") & hisp == "Non-Hispanic", "White",
race %chin% c("White") & hisp == "Hispanic", "Hispanic",
##Hispanic getting at mestizos, i.e. Amerindian with Iberian (Spanish) admixture -
## what most people think of as "Hispanic", but classified as "White"
##- ignoring Black and Asian hispanic. There is a very small percentage of white hispanics
## with no amerindian ancestry who according to this
## criterion should be classified as 'White', but its negligible.
race %chin% c("Black", "White-Black", "Black-Asian", "Black-Hawaiian", "Black-American Indian"), "Black",
race %chin% c("Asian", "Hawaiian", "Asian-Hawaiian"), "Asian", ##Asian/PAcific Islander/Hawaiian
race %chin% c("American Indian"), "American Indian",
##all others, it not missing, "Other"
!is.na(race), "Other",
default = NA_character_
)
}
get_race_category_v2 <- function(race, hisp){
data.table::fcase(
hisp == "Hispanic", "Hispanic",
race %chin% c("White") & hisp == "Non-Hispanic", "White",
race %chin% c("Black") & hisp == "Non-Hispanic", "Black",
race %chin% c("Asian") & hisp == "Non-Hispanic", "Asian",
!is.na(race), "Other",
default = NA_character_
)
}
process_ncvs_002_files <- function(dt){
require(data.table)
require(magrittr)
dt[, .(
IDHH,
HH_WEIGHT = V2116,
WGTHHCY, ##ADJUSTED HOUSEHOLD WEIGHT - COLLECTION YEAR
hh_Race0 = data.table::fcase(
V2031 == 1, "White", ##White, but not specifying Hispanic
V2031 == 2, "Black",
V2031 == 6, "White-Black",
V2031 %in% c(3,21), "Other",
V2031 == 22, "White-Other",
V2031 == 23, "Black-Other",
V2031 == 24, "White-Black-Other",
default = NA_character_),
pp_Race0 = get_race(V2040A),
pp_Hisp = fcase(V2041 == 1, "Hispanic", V2041 == 2, "Non-Hispanic", default = NA_character_),
ref_Race0 = get_race(V2049A),
ref_Hisp = fcase(V2050 == 1, "Hispanic", V2050 == 2, "Non-Hispanic", default = NA_character_))] %>%
.[, `:=`(
hh_Race = data.table::fcase(
hh_Race0 %chin% c("White","White-Other"), "White/Hispanic",
hh_Race0 %chin% c("Black", "Black-Other", "White-Black"), "Black",
##Note: due to social construction, etc. White-Black is coded as Black, but this is negligible
hh_Race0 %chin% c("Other", "White-Black-Other"), "Other",
default = NA_character_),
pp_Race = get_race_category(pp_Race0, pp_Hisp),
ref_Race = get_race_category(ref_Race0, ref_Hisp)
)]
}
process_ncvs_003_files <- function(dt){
require(data.table)
require(magrittr)
dt[, .(
YEARQ,
IDHH, IDPER,
WGTPERCY,
PP_weight = V3080,
Num_incidents = V3081, ##Num Incidents
Race0 = get_race(V3023A),
Hisp = data.table::fcase(V3024 == 1, "Hispanic", V3024 == 2, "Non-Hispanic", default = NA_character_))] %>%
.[, `:=` (
Race = get_race_category(Race0, Hisp),
Race_v2 = get_race_category_v2(Race0, Hisp)
)]
}
process_ncvs_004_files <- function(dt){
require(data.table)
require(magrittr)
## In 2015, incident weight is called V4527
## "Beginning in 2016, the incident weight (V4527) was adjusted to account for series victimizations
##and was renamed SERIES_IWEIGHT."
if("V4527" %in% names(dt) & !"SERIES_IWEIGHT" %in% names(dt)){
if(max(dt$V4527, na.rm=TRUE) > 0){
data.table::setnames(dt, old = c("V4527"), new = c("SERIES_IWEIGHT"), skip_absent = FALSE)
}
}
##Rule V4022 != 1 excludes cases outside US
dt[V4022 != 1] %>%
.[, V4016 := fifelse(V4016 %in% 11:996, 10, V4016)] %>% ##recode series, no greater than 10]
.[, .(
YEARQ,
Year = V4015,
Incident_num = V4012,
Crime = get_crime(V4529),
Crime_type = recode_serious_crimes(V4529),
Crime_code = V4529,
IDHH,
IDPER,
WGTVICCY = fifelse(V4019 == 2, WGTVICCY * V4016, WGTVICCY), ##adust for series
SERIES_WEIGHT,
Incident_Weight = SERIES_IWEIGHT,
off_Race0 = data.table::fcase(
V4246C == 1 | V4281 == 1 | V4285A == 2, "Black",
V4246B == 1 | V4280 == 1 | V4285A == 1, "White",
V4246D == 1 | V4282A == 1 | V4285A == 3, "Native American",
V4246E == 1 | V4282B == 1 | V4285A == 4, "Asian",
V4246F == 1 | V4282C == 1 | V4285A == 5, "Hawaiian",
default = NA_character_),
##Excluding multiple offenders of various races
off_Race0_v2 = data.table::fcase(
V4285A %in% 1:5, "Multiple",
V4246C == 1 | V4281 == 1, "Black",
V4246B == 1 | V4280 == 1, "White",
V4246D == 1 | V4282A == 1, "Native American",
V4246E == 1 | V4282B == 1, "Asian",
V4246F == 1 | V4282C == 1, "Hawaiian",
default = NA_character_),
off_Hisp = data.table::fcase(
V4237A == 1 | V4252A == 1 | V4252B %in% c(1), "Hispanic",
V4237A == 2 | V4252A == 2 | V4252B %in% c(2), "Non-Hispanic",
default = NA_character_))] %>%
.[, `:=`(
`Offender Race` = data.table::fcase(
off_Race0 == "White" & off_Hisp == "Non-Hispanic", "White",
off_Race0 == "White" & is.na(off_Hisp), "White", ## Counting White with missing Hispanic designation as White
off_Race0 == "White" & off_Hisp == "Hispanic", "Hispanic",
off_Race0 == "Black", "Black",
off_Race0 %chin% c("Asian", "Hawaiian"), "Asian",
off_Race0 == "Native American", "Native American",
default = NA_character_),
##Excluding all hispanic; Other = Hawaiian, Native American
`Offender Race v2` = data.table::fcase(
off_Hisp == "Hispanic", "Hispanic",
off_Race0 == "White" & off_Hisp == "Non-Hispanic", "White",
off_Race0 == "Black" & off_Hisp == "Non-Hispanic", "Black",
off_Race0 == "Asian" & off_Hisp == "Non-Hispanic", "Asian",
off_Race0 %chin% c("Native American", "Hawaiian"), "Other",
default = NA_character_),
##version 2 + excluding multiple
`Offender Race v3` = data.table::fcase(
off_Hisp == "Hispanic", "Hispanic",
off_Race0_v2 == "White" & off_Hisp == "Non-Hispanic", "White",
off_Race0_v2 == "Black" & off_Hisp == "Non-Hispanic", "Black",
off_Race0_v2 == "Asian" & off_Hisp == "Non-Hispanic", "Asian",
off_Race0_v2 == "Multiple", "Multiple Races",
off_Race0_v2 %chin% c("Native American", "Hawaiian"), "Other",
default = NA_character_)
)]
}
merge_and_summarise <- function(dt_004, dt_003,
keep_codes = 1:20,
grouping_vars = c("Weight_type")){
require(data.table)
weight_cols <- c("SERIES_WEIGHT", "Incident_Weight", "WGTPERCY", "UNWEIGHTED")
dt <- dt_004[Crime_code %in% keep_codes]
dt <- data.table::merge.data.table(x = dt, y = dt_003,
by = c("IDPER", "IDHH", "YEARQ"),
all.x = TRUE)
dt[, UNWEIGHTED := 1]
keep_vars <- unique(c(weight_cols,
grouping_vars,
"Crime", "Crime_code", "Race", "Offender Race"))
keep_vars <- keep_vars[which(keep_vars != "Weight_type")]
dt <- dt[, ..keep_vars]
weight_cols <- weight_cols[which(weight_cols %in% names(dt))]
dt <- data.table::melt.data.table(data = dt,
measure.vars = weight_cols,
variable.name = "Weight_type",
value.name = "Weight")
gVars <- unique(c("Weight_type", grouping_vars))
gVars <- gVars[which(gVars %in% names(dt))]
dt[, `:=`(
`Total Known Race` = sum(Weight[which(!is.na(`Offender Race`))], na.rm=TRUE),
`Total` = sum(Weight, na.rm=TRUE)
), by = gVars]
gVars <- unique(c("Weight_type", "Offender Race", grouping_vars))
gVars <- gVars[which(gVars %in% names(dt))]
dt <- dt[, .(
`Total Known Race` = first(`Total Known Race`),
`Total` = first(`Total`),
`Victimized by Offender Race` = sum(Weight, na.rm=TRUE)), by = gVars]
dt[, `:=`(
`Percent Known Race` = `Victimized by Offender Race`/`Total Known Race`,
`Percent Total` = `Victimized by Offender Race`/Total,
`Offender Race` = factor(`Offender Race`,
levels = c("White", "Black", "Hispanic",
"Asian", "Native American"))
)]
return(dt)
}
show_crime_summary <- function(df, grouping_vars = NULL,
use_weight = c("series", "incident",
"person", "unweighted")){
require(data.table)
require(reactable)
use_weight = match.arg(use_weight)
use_weight = switch(use_weight, "series" = "SERIES",
"incident" = "INCIDENT",
"person" = "WGTPERCY",
"unweighted" = "UNWEIGHTED")
dt <- data.table::as.data.table(df)
data.table::setnames(dt, skip_absent = TRUE,
old = c("Crime_type", "Weight_type"),
new = c("Offense", "Weight"))
dt <- dt[!is.na(`Offender Race`)]
dt[, Weight := dplyr::recode(Weight,
"Incident_Weight" = "INCIDENT",
"SERIES_WEIGHT" = "SERIES")]
keep_vars <- unique(c(grouping_vars, "Offender Race", "Offense",
"Weight", "Year",
"Victimizations",
"Percent",
"Percent Known Race"))
keep_vars <- keep_vars[which(keep_vars %in% names(dt))]
dt <- dt[, ..keep_vars]
if("Offense" %in% names(dt)){
dt[, Offense := factor(Offense, levels = c("Robbery",
"Assault",
"Rape/Sexual attack"))]
}
dt <- dt[Weight == use_weight]
dt[, Weight := NULL]
order_vars <- c("Offender Race", "Offense", "Year" )
order_vars <- order_vars[which(order_vars %in% names(dt))]
data.table::setorderv(dt, cols = order_vars)
grouping_vars <- grouping_vars[which(grouping_vars %in% names(dt))]
if(length(grouping_vars) == 0){grouping_vars <- NULL}
reactable::reactable(dt, striped = TRUE, highlight = TRUE,
bordered = TRUE,
pagination = FALSE,
compact = FALSE,
resizable = FALSE,
groupBy = grouping_vars,
defaultColDef = colDef(
minWidth = 135, align = "left",
style = list(fontSize = 12,
fontFamily = "'Roboto Condensed', 'Arial Narrow',
Merriweather, Arial,
Helvetica, sans-serif"),
format = list(cell = colFormat(separators = TRUE,
percent = TRUE,
digits = 2)),
headerStyle = list(fontWeight = "bold", fontSize = 16),
footerStyle = list(fontWeight = "bold"))
,columns = list(
Weight = colDef(align = "left",
minWidth = 85,
aggregate = "unique"),
`Offender Race` = colDef(align = "left",
minWidth = 95,
aggregate = "unique"),
`Year` = colDef(align = "center",
minWidth = 45,
aggregate = "unique",
format = colFormat(separators = FALSE,
percent = FALSE,
digits = 0)),
Victimizations = colDef(align = "center",
minWidth = 75,
aggregate = "sum",
format = colFormat(separators = TRUE,
percent = FALSE, digits = 0)),
Offense = colDef(aggregate = "unique"),
`Percent` = colDef(aggregate = "mean",
minWidth = 55,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE, digits = 2)),
`Percent Known Race` = colDef(aggregate = "mean",
minWidth = 55,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE, digits = 2))
)
)
}Data pertaining to interracial violent victimizations (excluding murder) can be obtained from the National Crime Victimization Survey (NCVS). The Bureau of Justice Statistics (BJS) provides the following description on their website:
“The Bureau of Justice Statistics’ (BJS) National Crime Victimization Survey (NCVS) is the nation’s primary source of information on criminal victimization. Each year, data are obtained from a nationally representative sample of about 240,000 interviews on criminal victimization, involving 160,000 unique persons in about 95,000 households…. The NCVS collects information on nonfatal personal crimes (i.e., rape or sexual assault, robbery, aggravated and simple assault, and personal larceny) … both reported and not reported to police.”
The BJS has made available on their website data pertaining to interracial violence for 2018 and 2019, which can be downloaded as excel files.
Criminal Victimization, 2019, click the link Data tables to download the zipped excel files. Data pertaining to interracial violence can be found in Table 15 (file cv19t15.csv).
Criminal Victimization, 2018, click the link Data tables to download the zipped excel files. Data pertaining to interracial violence can be found in Table 14 (file cv18t14.csv).
Unfortunately, the BJS has not published analogous files for earlier versions of the survey from 2015 and 2016, and the format of the data they do publish changes from year to year. However, the raw data can be obtained from the Inter-university Consortium for Political and Social Research (ICPSR). The drawback is that these data are not easily accessible to the general public. The files are huge, require code books to interpret, and are generally unmanageable without some prior experience in coding and/or data analysis.
My presentation of the ICPSR data is mostly reproducible but requires that you first download the .tsv formatted files from the following links:
For practitioners of R, note that because the files are so large, I load and process the files using the data.table package, which might not be as familiar as the tidyverse or base R. For more information on data.table syntax, see: https://rdatatable.gitlab.io/data.table/index.html .
Loading data…
##2015 Data
nc_15_003 <- data.table::fread(paste0(myDataFolder, "DATA/NCVS-ICPSR-2015-36448/DS0003/36448-0003-Data.tsv")) %>%
process_ncvs_003_files(.)
nc_15_004 <- data.table::fread(paste0(myDataFolder, "DATA/NCVS-ICPSR-2015-36448/DS0004/36448-0004-Data.tsv")) %>%
process_ncvs_004_files(.)
##2016 Data
nc_16_003 <- data.table::fread(paste0(myDataFolder, "DATA/NCVS-ICPSR-2016-36828/DS0003/36828-0003-Data.tsv")) %>%
process_ncvs_003_files(.)
nc_16_004 <- data.table::fread(paste0(myDataFolder,"DATA/NCVS-ICPSR-2016-36828/DS0004/36828-0004-Data.tsv")) %>%
process_ncvs_004_files(.)
##2018 Data
nc_18_003 <- data.table::fread(paste0(myDataFolder,"DATA/NCVS-ICPSR-2018-37297/DS0003/37297-0003-Data.tsv")) %>%
process_ncvs_003_files(.)
nc_18_004 <- data.table::fread(paste0(myDataFolder,"DATA/NCVS-ICPSR-2018-37297/DS0004/37297-0004-Data.tsv")) %>%
process_ncvs_004_files(.)d_vc_15 <- merge_and_summarise(nc_15_004, nc_15_003, keep_codes = 1:20,
grouping_vars = c("Weight_type")) %>%
.[, Year := 2015]
d_vc_16 <- merge_and_summarise(nc_16_004, nc_16_003, keep_codes = 1:20,
grouping_vars = c("Weight_type")) %>%
.[, Year := 2016]
d_vc_18 <- merge_and_summarise(nc_18_004, nc_18_003, keep_codes = 1:20,
grouping_vars = c("Weight_type")) %>%
.[, Year := 2018]
d_vc_all <- data.table::rbindlist(list(d_vc_15, d_vc_16, d_vc_18))
d_vc_all %>% show_crime_summary(., grouping_vars = c("Offender Race"))Below I include only criminal codes 1-13. These are offenses which are more likely to be reported and for which offenders are more likely to be arrested.
d_vc_15 <- merge_and_summarise(nc_15_004, nc_15_003, keep_codes = 1:13,
grouping_vars = c("Weight_type")) %>%
.[, Year := 2015]
d_vc_16 <- merge_and_summarise(nc_16_004, nc_16_003, keep_codes = 1:13,
grouping_vars = c("Weight_type")) %>%
.[, Year := 2016]
d_vc_18 <- merge_and_summarise(nc_18_004, nc_18_003, keep_codes = 1:13,
grouping_vars = c("Weight_type")) %>%
.[, Year := 2018]
d_vc_major <- data.table::rbindlist(list(d_vc_15, d_vc_16, d_vc_18))
d_vc_major %>% show_crime_summary(., grouping_vars = c("Offender Race"))d_vc_15 <- merge_and_summarise(nc_15_004, nc_15_003, keep_codes = 1:13,
grouping_vars = c("Weight_type", "Crime_type")) %>%
.[, Year := 2015]
d_vc_16 <- merge_and_summarise(nc_16_004, nc_16_003, keep_codes = 1:13,
grouping_vars = c("Weight_type", "Crime_type")) %>%
.[, Year := 2016]
d_vc_18 <- merge_and_summarise(nc_18_004, nc_18_003, keep_codes = 1:13,
grouping_vars = c("Weight_type", "Crime_type")) %>%
.[, Year := 2018]
d_vc_major_offense <- data.table::rbindlist(list(d_vc_15, d_vc_16, d_vc_18))
d_vc_major_offense %>% show_crime_summary(.,
grouping_vars = c("Offender Race",
"Offense"))Importantly, these data do not distinguish between Hispanic and Non-Hispanic Whites.
SOURCES:
Offenders
2015 - https://ucr.fbi.gov/nibrs/2015/tables/excels/offenders_race_by_offense_category_2015.xls/output.xls
2016 - https://ucr.fbi.gov/nibrs/2016/tables/excels/offenders_race_by_offense_category_2016.xls/output.xls
nibrs_offense <- readr::read_csv("Data/NIBRS/nibrs-race-by-offense.csv") %>%
tidyr::pivot_longer(-c(Offense, Year, Total),
names_to = "Race",
values_to = "offenders") %>%
dplyr::mutate(Offense = factor(Offense,
levels = c("Murder", "Robbery",
"Assault", "Rape")),
Race = dplyr::recode(Race, "White" = "White/Hispanic"),
Race = factor(Race, levels = c("White/Hispanic",
"Black",
"Asian",
"Native American",
"Hawaiian",
"Unknown")))
nibrs_offense_sum <- nibrs_offense %>%
dplyr::select(-Total) %>%
#dplyr::filter(Offense != "Murder") %>%
dplyr::group_by(Year) %>%
dplyr::mutate(
Total = sum(offenders),
`Total Known Race` = sum(offenders[which(Race != "Unknown")])
) %>%
dplyr::group_by(Year, Race) %>%
dplyr::summarise(
Offenders = sum(offenders),
Total = first(Total),
Percent = Offenders/Total,
`Offenders Known Race` = sum(offenders[which(Race != "Unknown")]),
`Total Known Race` = first(`Total Known Race`),
`Percent Known Race` = `Offenders Known Race`/`Total Known Race`
)nibrs_offense_sum %>%
dplyr::rename(`Offender Race` = Race) %>%
dplyr::arrange(Year,`Offender Race`) %>%
dplyr::select(`Offender Race`, Year,
`Percent of Total Offenders` = `Percent`,
`Percent Known Race` ) %>%
reactable::reactable(., striped = TRUE, highlight = TRUE,
bordered = TRUE, pagination = FALSE,
compact = FALSE, resizable = FALSE,
groupBy = c("Offender Race"),
defaultColDef = colDef(
#minWidth = 150,
style = list(fontSize = 12, fontFamily = "'Roboto Condensed',
'Arial Narrow', Merriweather, Arial, Helvetica, sans-serif"),
align = "left",
format = list(cell = colFormat(separators = TRUE,
percent = TRUE, digits = 2)),
headerStyle = list(fontWeight = "bold",
fontSize = 15),
footerStyle = list(fontWeight = "bold"))
,columns = list(
#Weight = colDef(align = "right"),
Year = colDef(aggregate = "unique",
format = colFormat(separators = FALSE,
percent = FALSE, digits = 0)),
`Percent of Total Offenders` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2)),
`Percent Known Race` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2))
)
)d_tbl <- nibrs_offense %>%
dplyr::select(-Total) %>%
dplyr::group_by(Year, Offense) %>%
dplyr::mutate(
Total = sum(offenders),
`Total Known Race` = sum(offenders[which(Race != "Unknown")])) %>%
dplyr::group_by(Year, Race, Offense) %>%
dplyr::summarise(
Offenders = sum(offenders),
Total = first(Total),
Percent = Offenders/Total,
`Offenders Known Race` = sum(offenders[which(Race != "Unknown")]),
`Total Known Race` = first(`Total Known Race`),
`Percent Known Race` = `Offenders Known Race`/`Total Known Race`,
.groups = "drop")
d_tbl %>%
dplyr::rename(`Offender Race` = Race) %>%
dplyr::arrange(Offense, `Offender Race`, Year) %>%
dplyr::select(Offense, `Offender Race`, Year,
`Percent of Total Offenders` = `Percent`,
`Percent Known Race` ) %>% #%>% DT::datatable(.) %>% DT::formatPercentage(., columns = 4:5)
reactable::reactable(., striped = TRUE, highlight = TRUE,
bordered = TRUE, pagination = FALSE,
compact = FALSE, resizable = FALSE,
groupBy = c("Offender Race", "Offense"),
defaultColDef = colDef(
#minWidth = 150,
style = list(fontSize = 12,
fontFamily = "'Roboto Condensed',
'Arial Narrow', Merriweather,
Arial, Helvetica, sans-serif"),
align = "left",
format = list(cell = colFormat(separators = TRUE,
percent = TRUE, digits = 2)),
headerStyle = list(fontWeight = "bold", fontSize = 15),
footerStyle = list(fontWeight = "bold"))
,columns = list(
#Weight = colDef(align = "right"),
Offense = colDef(aggregate = "unique"),
Year = colDef(aggregate = "unique",
format = colFormat(separators = FALSE,
percent = FALSE,
digits = 0)),
`Percent of Total Offenders` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2)),
`Percent Known Race` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2))
)
)Importantly, these data do not distinguish between Hispanic and Non-Hispanic Whites.
SOURCES:
Arrests
The files include the following crimes found in the above excel worksheets:
nibrs_arrest <- readr::read_csv("Data/NIBRS/nibrs-race-by-arrest.csv") %>%
tidyr::pivot_longer(-c(Offense, Year, Total), names_to = "Race", values_to = "arrests") %>%
dplyr::mutate(Offense = factor(Offense, levels = c("Murder", "Robbery", "Assault", "Rape")),
Race = dplyr::recode(Race, "White" = "White/Hispanic"),
Race = factor(Race, levels = c("White/Hispanic", "Black", "Asian",
"Native American", "Hawaiian", "Unknown")))
nibrs_arrest_sum <- nibrs_arrest %>%
dplyr::select(-Total) %>%
#dplyr::filter(Offense != "Murder") %>%
dplyr::group_by(Year) %>%
dplyr::mutate(
Total = sum(arrests),
`Total Known Race` = sum(arrests[which(Race != "Unknown")])
) %>%
dplyr::group_by(Year, Race) %>%
dplyr::summarise(
Arrests = sum(arrests),
Total = first(Total),
Percent = Arrests/Total,
`Arrests Known Race` = sum(arrests[which(Race != "Unknown")]),
`Total Known Race` = first(`Total Known Race`),
`Percent Known Race` = `Arrests Known Race`/`Total Known Race`
)nibrs_arrest_sum %>%
dplyr::rename(`Offender Race` = Race) %>%
dplyr::arrange(Year,`Offender Race`) %>%
dplyr::select(`Offender Race`, Year,
`Percent of Total Offenders` = `Percent`,
`Percent Known Race` ) %>%
reactable::reactable(., striped = TRUE, highlight = TRUE,
bordered = TRUE, pagination = FALSE,
compact = FALSE, resizable = FALSE,
groupBy = c("Offender Race"),
defaultColDef = colDef(
#minWidth = 150,
style = list(fontSize = 12,
fontFamily = "'Roboto Condensed',
'Arial Narrow', Merriweather,
Arial, Helvetica, sans-serif"),
align = "left",
format = list(cell = colFormat(separators = TRUE,
percent = TRUE, digits = 2)),
headerStyle = list(fontWeight = "bold", fontSize = 15),
footerStyle = list(fontWeight = "bold"))
,columns = list(
#Weight = colDef(align = "right"),
Year = colDef(aggregate = "unique",
format = colFormat(separators = FALSE,
percent = FALSE,
digits = 0)),
`Percent of Total Offenders` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2)),
`Percent Known Race` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2))
)
)d_tbl <- nibrs_arrest %>%
dplyr::select(-Total) %>%
dplyr::group_by(Year, Offense) %>%
dplyr::mutate(
Total = sum(arrests),
`Total Known Race` = sum(arrests[which(Race != "Unknown")])
) %>%
dplyr::group_by(Year, Race, Offense) %>%
dplyr::summarise(
Arrests = sum(arrests),
Total = first(Total),
Percent = Arrests/Total,
`Arrests Known Race` = sum(arrests[which(Race != "Unknown")]),
`Total Known Race` = first(`Total Known Race`),
`Percent Known Race` = `Arrests Known Race`/`Total Known Race`,
.groups = "drop")
d_tbl %>%
dplyr::rename(`Offender Race` = Race) %>%
dplyr::arrange(Offense, `Offender Race`, Year) %>%
dplyr::select(Offense, `Offender Race`, Year,
`Percent of Total Offenders` = `Percent`,
`Percent Known Race` ) %>% #%>% DT::datatable(.) %>% DT::formatPercentage(., columns = 4:5)
reactable::reactable(., striped = TRUE, highlight = TRUE,
bordered = TRUE, pagination = FALSE,
compact = FALSE, resizable = FALSE,
groupBy = c("Offender Race", "Offense"),
defaultColDef = colDef(
#minWidth = 150,
style = list(fontSize = 12, fontFamily = "'Roboto Condensed',
'Arial Narrow', Merriweather, Arial, Helvetica, sans-serif"),
align = "left",
format = list(cell = colFormat(separators = TRUE, percent = TRUE, digits = 2)),
headerStyle = list(fontWeight = "bold", fontSize = 15),
footerStyle = list(fontWeight = "bold"))
,columns = list(
#Weight = colDef(align = "right"),
Offense = colDef(aggregate = "unique"),
Year = colDef(aggregate = "unique",
format = colFormat(separators = FALSE,
percent = FALSE,
digits = 0)),
`Percent of Total Offenders` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2)),
`Percent Known Race` = colDef(aggregate = "mean",
minWidth = 75,
align = "center",
format = colFormat(separators = TRUE,
percent = TRUE,
digits = 2))
)
)