| Title: | R Wrapper for the FBI Crime Data Explorer (CDE) API |
|---|---|
| Description: | An R wrapper for the FBI Crime Data Explorer (CDE) API (<https://cde.ucr.cjis.gov/LATEST/>) providing access to UCR and NIBRS crime data. Functions cover lookups (agencies, offense codes, states), summarized crime data, arrest statistics, NIBRS incident-level data, Supplemental Homicide Reports (SHR), and police employment statistics. No API key is required for the current CDE host. Based on the original fbi package by Jacob Kaplan (https://github.com/jacobkap/fbi). |
| Authors: | Jared E. Knowles [aut, cre] |
| Maintainer: | Jared E. Knowles <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-10-15 21:27:00 UTC |
| Source: | https://github.com/civilytics/fbi_cde |
Attributes campus and other special-district agencies (any agency of type
"University or College", "Other", or "Other State Agency" — CDE has
no literal "transit" or "airport" type) to a place by point-in-polygon of
their headquarters coordinates against Census place boundaries. Appends
them to a place_agencies() result.
add_place_spatial_members(x, vintage = NULL, places_fun = NULL)add_place_spatial_members(x, vintage = NULL, places_fun = NULL)
x |
A data.frame as returned by |
vintage |
Optional Census boundary year passed to |
places_fun |
Function used to fetch place polygons, called as
|
This is opt-in and best-effort. It requires sf and tigris (both in
‘Suggests’) and downloads boundary shapefiles. Without them the
function emits a message and returns its input unchanged.
Sheriffs and state police are never candidates: unlike a university police department — whose headquarters genuinely sits on its campus inside the city — a sheriff's HQ point carries no information about its jurisdiction. That restriction is what makes point-in-polygon defensible for this tier.
Agencies with no coordinates in the bundled table cannot be placed: 271 of the 2,324 embedded-tier agencies (11.7%) have none and can never be spatially attributed by this function.
x with spatially-attributed rows appended. On those rows
place_type is "incorporated" or "cdp" (Census Designated Place, i.e.
unincorporated) and place_fips is the GEOID of the polygon the
agency's headquarters falls in: best-effort enrichment, unlike the
place_fips of the place's own agency, which is the promised key
described in place_agencies(). cousub_fips is NA on appended rows.
The rows of x keep their codes. Appended rows carry
attribution = "point_in_polygon". Their
agency_class decides whether get_place_crime_detail() queries them by
default: "campus" rows yes; "special" and "state" rows only when
requested.
## Not run: x <- place_agencies("Berkeley", "CA") add_place_spatial_members(x) ## End(Not run)## Not run: x <- place_agencies("Berkeley", "CA") add_place_spatial_members(x) ## End(Not run)
CBSA definitions are revised periodically and counties move between metros,
so results are only reproducible against a stated vintage. Sourced from the
shipped data's own "vintage" attribute (stamped in
data-raw/cbsa_crosswalk.R), not duplicated as an independent literal, so a
rebuild that bumps the vintage cannot leave this constant stale. The 2023L
below is a fallback for the (very unlikely) case where cbsa_crosswalk
carries no "vintage" attribute; .onLoad() in R/fips.R overwrites it
from the data as soon as the namespace is available – sysdata.rda is not
guaranteed to be loaded yet while this file's top-level code is parsed, so
the real read cannot happen here directly.
CBSA_VINTAGECBSA_VINTAGE
An integer scalar.
Returns the base URL for the FBI Crime Data Explorer API.
Can be overridden via getOption("fbiCDE.cde.base_url") or
Sys.getenv("FBI_CDE_BASE_URL") (for tests).
cde_base_url()cde_base_url()
A character string with the base URL.
cde_base_url()cde_base_url()
Constructs the path portion of a CDE API endpoint URL from its components.
cde_path(type, level, offense = NULL)cde_path(type, level, offense = NULL)
type |
Character string with the endpoint type
(e.g. |
level |
Character string with the geographic level. One of
|
offense |
Optional character string with the offense identifier
(e.g. |
A character string with the API path, e.g.
"summarized/national/V" or "shr/state/CA".
cde_path("summarized", "national", "V") cde_path("summarized", "state/CA", "V") cde_path("shr", "agency/CA0010900")cde_path("summarized", "national", "V") cde_path("summarized", "state/CA", "V") cde_path("shr", "agency/CA0010900")
Formats year values and assembles a named list of query parameters for CDE API endpoint calls.
cde_query(from, to, type = NULL, four_digit_year = FALSE)cde_query(from, to, type = NULL, four_digit_year = FALSE)
from |
Character string or numeric with the start date/year.
When |
to |
Character string or numeric with the end date/year.
Same format rules as |
type |
Optional character string with the query type
(e.g. |
four_digit_year |
Logical; when |
A named list of query parameters, e.g.
list(from = "01-2015", to = "12-2020", type = "counts").
cde_query("01-2015", "12-2020", type = "counts") cde_query(2015, 2020, four_digit_year = TRUE)cde_query("01-2015", "12-2020", type = "counts") cde_query(2015, 2020, four_digit_year = TRUE)
Returns every agency in the bundled agency table whose county and state
match, classified by agency_class. This is an attribution model, not a
spatial one: it reports the agencies attributed to a county, not crime known
to have occurred there. It returns every class; the crime functions
(get_county_crime_detail(), get_metro_crime_detail()) then choose which
classes to query.
county_agencies(county, state)county_agencies(county, state)
county |
County name (case-insensitive; e.g. |
state |
Two-letter state abbreviation (e.g. |
A data.frame with columns ori, agency_name, agency_type_name,
agency_class, county_name, state_abbr, county_fips,
latitude, longitude, agency_county_names. county_name and
county_fips (5-digit, character, preserving leading zeros) identify the
queried county on every row. agency_county_names is the CDE's own county
list for the agency: semicolon-separated for an agency that polices several
counties (e.g. Columbus PD, "DELAWARE; FAIRFIELD; FRANKLIN"). Such an
agency is attributed in full to each of its counties, so summing results
across counties counts it more than once. agency_class is one of
"county_primary" (sheriff, parish), "municipal" (city police),
"campus", "state" (state police and other state agencies),
"special" (transit, school, airport, port, park and railroad police,
task forces) or "tribal". Returns a zero-row frame (with a warning) if
no agencies match.
The CDE assigns no county to three agencies that each police a whole county or county-equivalent, so the package attributes them itself, by ORI:
New York City Police Department (NY0303000): the five boroughs, Bronx,
Kings, New York, Queens and Richmond counties.
Metropolitan Police Department of the District of Columbia
(DCMPD0000): the District of Columbia.
Baltimore City Sheriff's Office (MD0040600): Baltimore city.
Connecticut agencies are also attributed to their planning region, the
county equivalent Connecticut adopted in 2022 and the unit its metro areas
are built from, as the CDE's live agency directory reports it. Query either
a traditional county (county_agencies("Hartford", "CT")) or a region
(county_agencies("Capitol Planning Region", "CT")), but do not add the
two systems together: every agency is in one of each. Six agencies have no
region in the directory (the state police, the DMV, two tribal agencies,
and Yale and UConn Health, which it lists under other identifiers).
The NYPD reports one series for the whole city; the CDE has no borough
breakdown. Like any multi-county agency it is attributed in full to each
of its counties, so county_agencies("Kings", "NY") includes the NYPD, and
the crime functions return citywide NYPD figures for Brooklyn, with
New York City's population. A borough's results therefore describe the
city, not the borough. Use the New York metro, or the NYPD itself, rather
than summing boroughs. For these agencies agency_county_names holds the
package's attribution, not a list from the CDE.
## Not run: county_agencies("Alameda", "CA") ## End(Not run)## Not run: county_agencies("Alameda", "CA") ## End(Not run)
Map a state + county name to a 5-digit county FIPS code using the FBI's internal agency-to-county mapping and a tigris-derived crosswalk.
county_to_fips(state, county) counties_with_fips()county_to_fips(state, county) counties_with_fips()
state |
A two-letter state abbreviation (e.g. |
county |
A county name as stored in |
The crosswalk is built at package build time from tigris::counties() and
covers 98.6% of unique (state, county) pairs in fbi_api_agencies.
Unresolvable cases:
county = "N/A" (agency has no county assigned — state police, tribal, etc.)
VALDEZ-CORDOVA (dissolved AK borough; split into Chugach & Copper River
census areas in 2015, no single FIPS exists)
A character string with the 5-digit county FIPS code (e.g. "06037")
or NA_character_ when the county cannot be resolved (e.g. "N/A" county,
dissolved boroughs). counties_with_fips() returns a data.frame with one
row per resolvable county: state_abbr, county_name (as the CDE spells
it), and county_fips.
county_to_fips("CA", "LOS ANGELES") #> "06037" county_to_fips("TX", "DEWITT") #> "48123" county_to_fips("MD", "BALTIMORE CITY") #> "24510" county_to_fips("MO", "ST LOUIS CITY") #> "29510" county_to_fips("AK", "N/A") #> NAcounty_to_fips("CA", "LOS ANGELES") #> "06037" county_to_fips("TX", "DEWITT") #> "48123" county_to_fips("MD", "BALTIMORE CITY") #> "24510" county_to_fips("MO", "ST LOUIS CITY") #> "29510" county_to_fips("AK", "N/A") #> NA
A dataset containing information about the 18,459 agencies included in the
FBI's API. It is a snapshot: NIBRS start dates run to September 2019, so the
NIBRS columns predate the large 2020-2021 transition. Use
get_agency_participation() for an agency's current NIBRS status.
fbi_api_agenciesfbi_api_agencies
A data frame with 18459 rows and 13 variables:
9-character unique ID for the agency (ORI)
Agency name
Type of department, e.g. City, County,
University or College. Louisiana's and Alaska's types are the CDE's
live directory's: the snapshot had typed every Louisiana agency
"Parish" and every Alaska agency by its borough or census area.
NA for 18 of those agencies that the directory no longer lists
State name
State abbreviation
Census division name
Census region name
Census region code
County name, uppercase. Semicolon-separated for an
agency that polices several counties; "N/A" when the agency has
no county. This is the CDE's own value: the geography functions also
attribute three "N/A" agencies (the NYPD, DC's Metropolitan
Police and the Baltimore City Sheriff) to their counties, which this
table does not show; see county_agencies
Logical: whether the agency reported to NIBRS as of the snapshot
Numeric agency latitude; NA when unknown
Numeric agency longitude; NA when unknown
Date the agency started reporting to NIBRS;
NA if it had not
https://cde.ucr.cjis.gov/LATEST/
Turns an object-of-label -> period -> value into a long/tidy data.frame
flatten_cde_json(obj)flatten_cde_json(obj)
obj |
A nested list/object from the CDE API with structure
|
A data.frame with columns: label, period, value
obj <- list( "United States Offenses" = list( "01-2015" = 27.6, "01-2016" = 29.62 ) ) ## Not run: flatten_cde_json(obj) ## End(Not run)obj <- list( "United States Offenses" = list( "01-2015" = 27.6, "01-2016" = 29.62 ) ) ## Not run: flatten_cde_json(obj) ## End(Not run)
Iterates over every state in get_states() and fetches its agency directory
from the CDE endpoint agency/byStateAbbr/{state} (the same endpoint the
participation functions use) to rebuild the full agency table. This issues
one request per state.
get_agencies()get_agencies()
A data.frame with one row per agency and one column per field the
API returns (currently ori, counties, is_nibrs, latitude,
longitude, state_abbr, state_name, agency_name, agency_type_name,
nibrs_start_date), all stored as character and sorted by ori. These
field names follow the live API and differ from the bundled
fbi_api_agencies snapshot (e.g. counties rather than county_name).
States whose request fails are skipped with a warning and listed in
attr(x, "failed_states").
## Not run: agencies <- get_agencies() head(agencies) ## End(Not run)## Not run: agencies <- get_agencies() head(agencies) ## End(Not run)
Get agency-level crime data from the UCR Offenses Known and Clearances
get_agency_crime( ori, from = "01-2015", to = "12-2020", offense = "V", comparison = FALSE )get_agency_crime( ori, from = "01-2015", to = "12-2020", offense = "V", comparison = FALSE )
ori |
A string of the 9-character ORI code for the desired agency. |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
Offense code (default "V" for violent crime). See
|
comparison |
If |
A data.frame with columns geography, offense (the requested
code), measure ("offenses" or "clearances"), period, count,
rate (per 100,000 population, for that month), population (the
population the series covers) and participated_population (the
population of the agencies that reported that month). Their ratio is the
reporting coverage: a state or national count below full coverage is the
sum of the agencies that reported, not an estimate for everyone. With
comparison = TRUE, two more columns follow geography: series
("agency", "state" or "national") and series_name (e.g.
"Oakland Police Department", "California", "United States").
Other UCR crime functions:
get_agency_participation(),
get_leoka(),
get_leoka_monthly(),
get_region_participation(),
get_reported_arson(),
get_reported_crime(),
get_state_participation()
## Not run: get_agency_crime("AK0010100") # The agency alongside its state and the nation get_agency_crime("CA0010900", from = "01-2019", to = "03-2019", comparison = TRUE) ## End(Not run)## Not run: get_agency_crime("AK0010100") # The agency alongside its state and the nation get_agency_crime("CA0010900", from = "01-2019", to = "03-2019", comparison = TRUE) ## End(Not run)
Get information about the selected agency including the 9-digit ORI, geographic information, type of agency, and whether they report to NIBRS.
get_agency_info(agency, state = NULL, ori_only = FALSE, exact_match = TRUE)get_agency_info(agency, state = NULL, ori_only = FALSE, exact_match = TRUE)
agency |
A string or vector of strings with the name of the agency you want to lookup (capitalized is ignored). |
state |
A string or vector of strings of state names. If used, returns only agencies in that state. This is useful in cases where multiple agencies have the same name in different states and you only want specific states. |
ori_only |
If TRUE (not default), returns only the ORI and the agency_name columns. |
exact_match |
If TRUE (default), finds matches based on exact match of agency name. Else,
treats each element of |
A data.frame with information about the agency - including ORI code and geographic information. The agency will have as many rows as agencies matched from the agency input.
get_agency_info("Oakland Police Department") get_agency_info("Oakland Police Department", state = "california")get_agency_info("Oakland Police Department") get_agency_info("Oakland Police Department", state = "california")
The current CDE API has no dedicated participation-rate endpoint: the
legacy participation/... paths this function used to call return 404,
and the participation/* namespace still present in the current API is
scoped to Use-of-Force agency reporting, not general UCR/NIBRS
participation (confirmed by inspecting the CDE web app's client bundle and
probing the live API – see Issue #1). This is a modernized
reimplementation: it reports whether ori currently reports to NIBRS,
sourced live from agency/byStateAbbr/ (state derived from the first two
characters of ori; Nebraska's NB and Guam's GM are looked up as NE
and GU), in place of the retired year-by-year SRS/NIBRS participation
series.
get_agency_participation(ori, key = get_api_key())get_agency_participation(ori, key = get_api_key())
ori |
A string of the 9-character ORI code for the desired agency. |
key |
API key for the legacy FBI API (not needed for CDE API). |
A one-row data.frame with columns: ori, agency_name, agency_type_name, state_abbr, state_name, county, is_nibrs, nibrs_start_date.
Jared E. Knowles, Civilytics Consulting
Other UCR crime functions:
get_agency_crime(),
get_leoka(),
get_leoka_monthly(),
get_region_participation(),
get_reported_arson(),
get_reported_crime(),
get_state_participation()
## Not run: get_agency_participation("CA0010900") ## End(Not run)## Not run: get_agency_participation("CA0010900") ## End(Not run)
Deprecated. The current CDE API (cde.ucr.cjis.gov/LATEST/) does not
require an API key. This function is retained only for backward compatibility
with code that previously used the legacy api.data.gov-hosted API.
get_api_key()get_api_key()
NULL. A deprecation message is printed on every call.
## Not run: get_api_key() ## End(Not run)## Not run: get_api_key() ## End(Not run)
Retrieves monthly arrest counts for an agency, a state, or the nation, for
all offenses or one, from the CDE API endpoint arrest/<level>/<code>
with type=counts.
get_arrest_count( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "all", comparison = FALSE )get_arrest_count( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "all", comparison = FALSE )
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
|
comparison |
If |
A data.frame with one row per month: geography, offense
("all", or the API's spelling of the offense name), measure
("arrests"), period, count, rate (per 100,000 population, for
that month), and the population and participated_population
described in get_agency_crime() (their ratio is the reporting
coverage). With comparison = TRUE, series and series_name columns
follow geography, as in get_agency_crime().
Other UCR arrest functions:
get_arrest_demographics(),
get_arrest_demographics_all(),
list_ucr_arrest_offenses()
## Not run: get_arrest_count(ori = "CA0010900") get_arrest_count(state_abb = "CA") get_arrest_count() get_arrest_count(state_abb = "CA", offense = "Robbery") get_arrest_count(state_abb = "CA", offense = "Drug/Narcotic Offenses") ## End(Not run)## Not run: get_arrest_count(ori = "CA0010900") get_arrest_count(state_abb = "CA") get_arrest_count() get_arrest_count(state_abb = "CA", offense = "Robbery") get_arrest_count(state_abb = "CA", offense = "Drug/Narcotic Offenses") ## End(Not run)
Retrieves arrest counts broken down by demographic categories (sex, age by
sex, race) over the date range, for all offenses or one. Uses the CDE API
endpoint arrest/<level>/<code> with type=totals. With an offense this is
the offense-by-age cross-tabulation: juvenile arrests for larceny, say.
get_arrest_demographics( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "all" )get_arrest_demographics( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "all" )
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
|
A data.frame with columns: geography, offense, period, demographic_type, demographic_value, count
The API's all-offense demographics leave out arrests filed under the five
"(Unspecified)" offense codes (140, 150, 151, 156 and 170, e.g. "Drug
Abuse Violations (Unspecified)"), although its all-offense counts include
them: in Ohio in 2023, 883 of 188,836 arrests, 57 of them juvenile.
Summing get_arrest_demographics() over the offense names includes them.
Other UCR arrest functions:
get_arrest_count(),
get_arrest_demographics_all(),
list_ucr_arrest_offenses()
## Not run: get_arrest_demographics(ori = "CA0010900") get_arrest_demographics(state_abb = "CA") get_arrest_demographics(state_abb = "OH", offense = "Larceny") ## End(Not run)## Not run: get_arrest_demographics(ori = "CA0010900") get_arrest_demographics(state_abb = "CA") get_arrest_demographics(state_abb = "OH", offense = "Larceny") ## End(Not run)
Deprecated. Use get_arrest_demographics(), which takes an
offense. This alias returns all-offense demographics (offense = "all")
and emits a warning. It is retained for backward compatibility and may be
removed in a future release.
get_arrest_demographics_all(...)get_arrest_demographics_all(...)
... |
Arguments passed to |
A data.frame with columns: geography, offense, period, demographic_type, demographic_value, count
Other UCR arrest functions:
get_arrest_count(),
get_arrest_demographics(),
list_ucr_arrest_offenses()
## Not run: get_arrest_demographics_all(state_abb = "CA") ## End(Not run)## Not run: get_arrest_demographics_all(state_abb = "CA") ## End(Not run)
Resolves the single county_primary ORI for a county and returns its own
get_agency_crime() series. This disambiguates "the county sheriff's own
reported crime" from "crime aggregated across the county"
(get_county_crime_detail()).
get_county_agency_crime( county, state, offense = "V", from = "01-2015", to = "12-2020", comparison = FALSE )get_county_agency_crime( county, state, offense = "V", from = "01-2015", to = "12-2020", comparison = FALSE )
county |
County name (case-insensitive). |
state |
Two-letter state abbreviation. |
offense |
Offense code (default |
from, to
|
Date range in |
comparison |
If |
The get_agency_crime() data.frame for the county's primary agency.
## Not run: get_county_agency_crime("Alameda", "CA") ## End(Not run)## Not run: get_county_agency_crime("Alameda", "CA") ## End(Not run)
Sums itemized agency-level detail (from get_county_crime_detail()) into a
single county-wide series. Unlike the FBI's published county rate, this
function never emits a bare rate: every row carries the chosen denominator
value, which denominator was used (denominator_type), and a
coverage_fraction (participated / total population) so the user can see
exactly how much of the county is covered by reporting agencies.
get_county_crime(detail, denominator = "jurisdiction_pop")get_county_crime(detail, denominator = "jurisdiction_pop")
detail |
A data.frame as returned by |
denominator |
Denominator strategy. One of:
|
The default denominator ("jurisdiction_pop") sums each agency's own
population column. Empirical probes confirm this is coherent: a sheriff's
population is the unincorporated remainder it polices, and contract cities
report under their own ORI — so the sum of jurisdiction_pop approximates
the full county with no double-count between sheriff and cities. Use
denominator = "participated_pop" for a coverage-consistent rate (drops
uncovered months), or denominator = "census_pop" to supply an external
Census population (requires the county_fips column from
county_agencies() and a Census join).
One exception: an agency that polices several counties reports a single
series, and it is counted in full in each of its counties, count and
population alike. Columbus PD puts all of Columbus in Delaware and
Fairfield counties' totals as well as Franklin's, and the NYPD makes every
borough's total New York City's. Those rows are the ones whose
agency_county_names lists more than one county; drop them from detail
first to exclude such agencies.
A period in which no agency reported has an NA count and rate, not 0;
coverage_fraction is then 0. Rows are in chronological order.
A data.frame with columns: county_name, state_abbr, offense,
period, count (sum of reported counts; NA when no agency reported),
population (the denominator
value used), participated_population (sum of participated populations),
rate (count / population * 1e5), denominator_type (which strategy was
used), and coverage_fraction (participated_population / population).
Returns a zero-row frame with correct columns if detail is empty. If
detail carries attr(detail, "dropped") (agencies whose request failed
in get_county_crime_detail()), the result warns and keeps that attribute:
those agencies are missing from every total, including the denominator.
vignette("estimates") for reported, estimated and imputed
crime.
## Not run: detail <- get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2019") get_county_crime(detail) # Coverage-consistent rate instead of the full jurisdiction denominator. get_county_crime(detail, denominator = "participated_pop") ## End(Not run)## Not run: detail <- get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2019") get_county_crime(detail) # Coverage-consistent rate instead of the full jurisdiction denominator. get_county_crime(detail, denominator = "participated_pop") ## End(Not run)
Fans out one request per member agency and returns their crime series
unsummed — one row per agency-period — with each agency's agency_class,
coverage (population, participated_population, reported), and a
per-agency rate (count / participated_population * 1e5). This is the
transparent, power-user primitive; it applies no aggregation and takes no
stance on denominators.
get_county_crime_detail( county, state, offense = "V", from = "01-2015", to = "12-2020", agency_class = NULL, include_statewide = FALSE, progress = FALSE )get_county_crime_detail( county, state, offense = "V", from = "01-2015", to = "12-2020", agency_class = NULL, include_statewide = FALSE, progress = FALSE )
county |
County name (case-insensitive). |
state |
Two-letter state abbreviation. |
offense |
Offense code (default |
from, to
|
Date range in |
agency_class |
Optional character vector of classes to query instead
of the default set ( |
include_statewide |
If |
progress |
If |
By default it queries the agencies whose jurisdiction is a specific area
below the state: the sheriff, city police and campus police. Add state
agencies with include_statewide = TRUE. Special-purpose agencies (transit,
school, airport, port, park and railroad police, task forces) and tribal
agencies are queried only when named in agency_class: the first group
mixes single-site agencies with multi-county task forces attributed to one
county, and how tribal agencies should attribute to counties is unresolved.
An agency that polices several counties reports one series, which is
returned in full for each of its counties: Columbus PD's rows are the same
for Delaware, Fairfield and Franklin counties, OH. The extreme case is New
York City, where the NYPD is the police of all five boroughs: any borough
returns citywide NYPD counts with New York City's population. Do not
sum counties that share an agency; see county_agencies(). Such rows are
the ones whose agency_county_names lists more than one county.
A data.frame with one row per agency-period: the agency metadata from
county_agencies() (including county_fips, which join_census_pop()
needs, and agency_county_names, the CDE's own county list), then
offense, period, count, population,
participated_population, rate, and reported. Agencies whose request
or parse fails are dropped with a warning; their ORIs are recorded in
attr(x, "dropped") and the errors in attr(x, "dropped_reasons").
## Not run: get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2019") ## End(Not run)## Not run: get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2019") ## End(Not run)
Counts of law enforcement officers feloniously killed, nationally, by year. Despite the program's name, these are not assault counts: the totals match the FBI's published felonious-killing figures (46 officers in 2020, 73 in 2021).
National only: the live leoka/ytd endpoint ignores state/agency query
parameters (verified against the live API – requests with and without
state/ori params return identical data), so the current CDE API has no
state- or agency-level LEOKA breakdown. Data is only available from 2020
onward; earlier years return an empty (0-row) result for that year and are
dropped, since leoka/ytd?year=<2015-2019> returns a null payload on
the live API.
get_leoka(from = 2020, to = 2024)get_leoka(from = 2020, to = 2024)
from |
Start year (4-digit), default 2020 (earliest year with data). |
to |
End year (4-digit), default 2024. |
A data.frame with one row per requested year with data and
columns: year, month (always NA; year-to-date totals have no month),
total_officers (officers feloniously killed), total_incidents (incidents
in which they were killed), and the _dod/_doi splits of each. The API
does not label those splits (they sum to the totals) and the package does
not interpret them.
Jared E. Knowles, Civilytics Consulting
Other UCR crime functions:
get_agency_crime(),
get_agency_participation(),
get_leoka_monthly(),
get_region_participation(),
get_reported_arson(),
get_reported_crime(),
get_state_participation()
## Not run: get_leoka(2020, 2024) ## End(Not run)## Not run: get_leoka(2020, 2024) ## End(Not run)
National only; see get_leoka().
get_leoka_monthly(year, month)get_leoka_monthly(year, month)
year |
4-digit year. |
month |
Month, 1-12. |
A one-row data.frame; see get_leoka() for columns.
Jared E. Knowles, Civilytics Consulting
Other UCR crime functions:
get_agency_crime(),
get_agency_participation(),
get_leoka(),
get_region_participation(),
get_reported_arson(),
get_reported_crime(),
get_state_participation()
## Not run: get_leoka_monthly(2020, 1) ## End(Not run)## Not run: get_leoka_monthly(2020, 1) ## End(Not run)
Fans out one request per member agency across the metro's counties and returns their crime series unsummed – one row per agency-period – with coverage columns and the CBSA metadata.
get_metro_crime_detail( metro, state = NULL, offense = "V", from = "01-2015", to = "12-2020", agency_class = NULL, include_statewide = FALSE, max_agencies = 150, progress = TRUE )get_metro_crime_detail( metro, state = NULL, offense = "V", from = "01-2015", to = "12-2020", agency_class = NULL, include_statewide = FALSE, max_agencies = 150, progress = TRUE )
metro |
A CBSA title (e.g. |
state |
Optional two-letter state abbreviation, used only to disambiguate an ambiguous short name. |
offense |
Offense code (default |
from, to
|
Date range in |
agency_class, include_statewide
|
Which agencies to query, as for
|
max_agencies |
Refuse to run if the filtered agency set is larger than
this (default |
progress |
If |
This can be an expensive call. A metro is the union of whole counties, so
the largest are very large: New York-Newark-Jersey City resolves to roughly
489 agencies, Chicago 314. Every agency is one sequential request. The median
CBSA is only 7 agencies, so the cost is highly skewed – which is why
max_agencies refuses the large cases up front rather than letting them run
silently for minutes.
No metro-level aggregate is provided. Summing across a metro raises the same denominator question the county aggregate deferred, and a metro's is harder (multi-state, mixed coverage).
A data.frame with one row per agency-period. Agencies whose request
or parse fails are dropped with a warning; their ORIs are recorded in
attr(x, "dropped") and the errors in attr(x, "dropped_reasons").
metro_agencies(), list_metros(), get_county_crime_detail().
## Not run: # A small micropolitan area is cheap. get_metro_crime_detail("Aberdeen, WA", from = "01-2019", to = "12-2019") ## End(Not run)## Not run: # A small micropolitan area is cheap. get_metro_crime_detail("Aberdeen, WA", from = "01-2019", to = "12-2019") ## End(Not run)
Returns the FBI's estimate: its published figure for a state or the
nation, which adds a statistical model's prediction for everything outside
NIBRS to what agencies reported in NIBRS. Each value comes with its 95%
confidence interval. Compare it with crime reported to the FBI using
imputation_gap().
get_nibrs_estimate(state_abb = NULL, year, offense = "V", table = "Offense")get_nibrs_estimate(state_abb = NULL, year, offense = "V", table = "Offense")
state_abb |
String for state abbreviation. If |
year |
A single year, e.g. |
offense |
A summary offense code ( |
table |
Which of the estimate's tables to return: |
The API publishes these estimates for the years in
nibrs_estimation_years (2021 and 2022), and only for states and the
nation: nothing for counties, cities or metro areas. A year it does not
cover fails with the API's own message listing the years it has. The
estimates come from nibrs-estimation/, the endpoint behind the CDE's
"NIBRS Estimates" page, which the CDE's public API documentation does not
list.
A data.frame with one row per category: geography, year,
offense, indicator (the estimates API's offense id), table,
variable (e.g. "Victim age"), category (e.g. "25-34"),
estimate, lower_bound and upper_bound. The offense total is the
"Offense" table's row with variable "Offense Count - Total".
Bounds are as published: NA where the FBI gives none, and below zero
for some small counts.
A geography the FBI publishes no estimate for (Arizona, in both years)
returns zero rows.
vignette("estimates") for reported, estimated and imputed
crime.
Other NIBRS functions:
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
## Not run: ca <- get_nibrs_estimate("CA", year = 2021) ca[ca$variable == "Offense Count - Total", ] ## End(Not run)## Not run: ca <- get_nibrs_estimate("CA", year = 2021) ca[ca$variable == "Offense Count - Total", ] ## End(Not run)
Retrieves offender counts by age, ethnicity, race or sex for one offense,
summed over the date range, from the CDE API endpoint
nibrs/<level>/<offense> with type=totals. Ages come in ten-year buckets
("10-19", ...).
get_nibrs_offender( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", variable = "race" )get_nibrs_offender( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", variable = "race" )
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
Offense code (default |
variable |
The variable to break offenders down by (default |
A data.frame with the columns described in get_nibrs_victim().
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
## Not run: get_nibrs_offender(state_abb = "OH", offense = "BUR", variable = "age", from = "01-2023", to = "12-2023") ## End(Not run)## Not run: get_nibrs_offender(state_abb = "OH", offense = "BUR", variable = "age", from = "01-2023", to = "12-2023") ## End(Not run)
Retrieves offense characteristics – the weapons involved, or the other
offenses reported in the same incidents – for one offense, summed over the
date range, from the CDE API endpoint nibrs/<level>/<offense> with
type=totals.
get_nibrs_offense( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", variable = "weapons" )get_nibrs_offense( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", variable = "weapons" )
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
Offense code (default |
variable |
|
A data.frame with the columns described in get_nibrs_victim().
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
## Not run: get_nibrs_offense(state_abb = "OH", offense = "ROB", variable = "weapons", from = "01-2023", to = "12-2023") ## End(Not run)## Not run: get_nibrs_offense(state_abb = "OH", offense = "ROB", variable = "weapons", from = "01-2023", to = "12-2023") ## End(Not run)
Retrieves victim counts by a demographic or situational variable (age,
ethnicity, location, race, relationship, sex) for one offense, summed over
the date range, from the CDE API endpoint nibrs/<level>/<offense> with
type=totals.
get_nibrs_victim( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", variable = "race" )get_nibrs_victim( ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", variable = "race" )
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
Offense code (default |
variable |
The variable to break victims down by (default |
An agency or state that did not report to NIBRS in the period returns zero rows, with a message.
A data.frame with columns: geography, offense (the code), period, demographic_type (the variable), demographic_value, count.
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
## Not run: get_nibrs_victim(state_abb = "OH", offense = "ROB", variable = "age", from = "01-2023", to = "12-2023") ## End(Not run)## Not run: get_nibrs_victim(state_abb = "OH", offense = "ROB", variable = "age", from = "01-2023", to = "12-2023") ## End(Not run)
Retrieves valid offense codes from the CDE lookup endpoint.
get_offense_codes(type = "crime-trend")get_offense_codes(type = "crime-trend")
type |
Character string for the offense type (e.g. "crime-trend",
"arrest", "hate-crime", "nibrs"). "nibrs" currently returns no codes
live ( |
A data.frame with offense codes and labels.
## Not run: offenses <- get_offense_codes() head(offenses) ## End(Not run)## Not run: offenses <- get_offense_codes() head(offenses) ## End(Not run)
Fans out one request per member agency and returns their crime series
unsummed — one row per agency-period — carrying agency_class, coverage
(population, participated_population, reported), a per-agency rate,
and the attribution that earned each agency its membership.
get_place_crime_detail( place, state, county = NULL, offense = "V", from = "01-2015", to = "12-2020", agency_class = NULL, include_statewide = FALSE, agencies = NULL, progress = FALSE )get_place_crime_detail( place, state, county = NULL, offense = "V", from = "01-2015", to = "12-2020", agency_class = NULL, include_statewide = FALSE, agencies = NULL, progress = FALSE )
place |
Place name (case-insensitive; e.g. |
state |
Two-letter state abbreviation (e.g. |
county |
Optional county name, needed only to disambiguate a place name that occurs in more than one county of the same state. |
offense |
Offense code (default |
from, to
|
Date range in |
agency_class |
Optional character vector of place classes to query
instead of the default set ( |
include_statewide |
If |
agencies |
Optional pre-resolved agency membership data.frame, e.g. the
output of Column presence is validated, but membership is not: a hand-built frame
can contain any ORI, including a sheriff or state police agency. The
supported path ( |
progress |
If |
In the common case a place has exactly one member agency, so this is a by-name wrapper over that agency's series. That is the value: ORI discovery is the package's primary friction, and this removes it.
No place-level aggregate is provided. Summing an opted-in campus agency into
a city total is a modeling choice, not arithmetic; see the county Layer 2
(get_county_crime()) for the shape that decision takes.
A data.frame with one row per agency-period, carrying: ori,
agency_name, agency_type_name, agency_class, place_name, the
Census codes place_type, place_fips and cousub_fips (see
place_agencies()), county_name, state_abbr, attribution, offense,
period, count, population, participated_population, rate, and
reported. Agencies whose request or parse fails are dropped with a
warning and recorded in attr(x, "dropped"). If filtering (via
agency_class/include_statewide) empties a non-empty agency set, a warning
names the place and the filter responsible, and a zero-row frame is
returned.
place_agencies(), add_place_spatial_members(),
impute_reporting_gaps() for filling reporting gaps in the result.
## Not run: get_place_crime_detail("Lufkin", "TX", from = "01-2019", to = "12-2019") # Compose with add_place_spatial_members() to reach campus agencies, which # are then queried by default alongside the city's own: x <- add_place_spatial_members(place_agencies("Berkeley", "CA")) get_place_crime_detail("Berkeley", "CA", agencies = x) ## End(Not run)## Not run: get_place_crime_detail("Lufkin", "TX", from = "01-2019", to = "12-2019") # Compose with add_place_spatial_members() to reach campus agencies, which # are then queried by default alongside the city's own: x <- add_place_spatial_members(place_agencies("Berkeley", "CA")) get_place_crime_detail("Berkeley", "CA", agencies = x) ## End(Not run)
Returns annual counts of sworn officers and civilian employees, by sex, for
an agency, a state, or the nation, from the CDE's police employment (pe)
endpoint.
get_police_employment( ori = NULL, state_abb = NULL, region = NULL, from = "2015", to = "2020" )get_police_employment( ori = NULL, state_abb = NULL, region = NULL, from = "2015", to = "2020" )
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
region |
Not supported: the CDE publishes no region-level police employment, and passing a region is an error. Sum the states instead. |
from, to
|
First and last year, as four-digit |
A data.frame with one row per year: year, male_officers,
female_officers, male_civilians, female_civilians, ori (the
requested geography), and the totals male_total, female_total,
civilians_total, officers_total and employees_total, then
participated_population (the population of the agencies that
reported) and employees_per_1000 (employees per 1,000 of that
population). For a state or the nation the counts are sums over the
agencies that reported, so they move with coverage: compare years by the
rate, not the count. Zero rows, with a message, when the CDE returns no
data.
## Not run: # Oakland Police Department, California get_police_employment("CA0010900", from = "2018", to = "2020") # California, and the nation get_police_employment(state_abb = "CA", from = "2018", to = "2020") get_police_employment(from = "2018", to = "2020") ## End(Not run)## Not run: # Oakland Police Department, California get_police_employment("CA0010900", from = "2018", to = "2020") # California, and the nation get_police_employment(state_abb = "CA", from = "2018", to = "2020") get_police_employment(from = "2018", to = "2020") ## End(Not run)
Aggregates get_state_participation() across every state in
region_name. Census region membership is taken from the bundled
fbi_api_agencies dataset – a fixed geography, not live crime data –
while each state's participation counts are fetched live. See
get_agency_participation() for why this is a modernized reimplementation
rather than the retired year-by-year SRS/NIBRS participation series.
get_region_participation(region_name, key = get_api_key())get_region_participation(region_name, key = get_api_key())
region_name |
String for the census region to get data for. See regions for valid values. |
key |
API key for the legacy FBI API (not needed for CDE API). |
A one-row data.frame with columns: region, total_agencies, nibrs_agencies, participation_rate.
Jared E. Knowles, Civilytics Consulting
Other UCR crime functions:
get_agency_crime(),
get_agency_participation(),
get_leoka(),
get_leoka_monthly(),
get_reported_arson(),
get_reported_crime(),
get_state_participation()
## Not run: get_region_participation("South") ## End(Not run)## Not run: get_region_participation("South") ## End(Not run)
get_reported_crime() for arson (offense = "ARS"): reported sums, not
the FBI's estimates. Called get_estimated_arson() until fbiCDE
0.2.0; the old name still works and warns.
get_reported_arson( state_abb = NULL, from = "01-2015", to = "12-2020", comparison = FALSE )get_reported_arson( state_abb = NULL, from = "01-2015", to = "12-2020", comparison = FALSE )
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
comparison |
If |
A data.frame with the columns described in get_agency_crime().
Other UCR crime functions:
get_agency_crime(),
get_agency_participation(),
get_leoka(),
get_leoka_monthly(),
get_region_participation(),
get_reported_crime(),
get_state_participation()
## Not run: get_reported_arson("CA") ## End(Not run)## Not run: get_reported_arson("CA") ## End(Not run)
Returns crime reported to the FBI: the sum of what the agencies that
reported each month sent, in either format (NIBRS, or the older summary
format). It is not the FBI's estimate, which adds a model's prediction
for everything outside NIBRS. Compare participated_population
with population to see how much of the state or nation a month covers.
The FBI's state and national summary-format estimates are published as a
bulk download only, which the package does not read; the
download recipe
fetches it.
get_reported_crime( state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", comparison = FALSE )get_reported_crime( state_abb = NULL, from = "01-2015", to = "12-2020", offense = "V", comparison = FALSE )
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2020"). |
offense |
Offense code (default "V" for violent crime). See
|
comparison |
If |
This function was called get_estimated_crime() until fbiCDE
0.2.0; the old name still works and warns.
A data.frame with the columns described in get_agency_crime().
vignette("estimates") for reported, estimated and imputed
crime.
Other UCR crime functions:
get_agency_crime(),
get_agency_participation(),
get_leoka(),
get_leoka_monthly(),
get_region_participation(),
get_reported_arson(),
get_state_participation()
## Not run: get_reported_crime("CA") ## End(Not run)## Not run: get_reported_crime("CA") ## End(Not run)
Retrieves homicide offense counts from the FBI's Supplemental Homicide Reports
via the CDE API endpoint shr/<level> with type=counts.
get_shr(ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2015")get_shr(ori = NULL, state_abb = NULL, from = "01-2015", to = "12-2015")
ori |
A string of the 9-character ORI code for the desired agency. |
state_abb |
String for state abbreviation. If |
from |
Start date in MM-YYYY format (default "01-2015"). |
to |
End date in MM-YYYY format (default "12-2015"). |
A data.frame with columns: geography, period, count
## Not run: # Gets national-level SHR data get_shr() # Gets California state-level SHR data get_shr(state_abb = "CA") # Gets Oakland PD SHR data get_shr(ori = "CA0010900") ## End(Not run)## Not run: # Gets national-level SHR data get_shr() # Gets California state-level SHR data get_shr(state_abb = "CA") # Gets Oakland PD SHR data get_shr(ori = "CA0010900") ## End(Not run)
See get_agency_participation() for why this is a modernized
reimplementation (share of agencies currently reporting NIBRS) rather than
the retired year-by-year SRS/NIBRS participation series.
get_state_participation(state_abb, key = get_api_key())get_state_participation(state_abb, key = get_api_key())
state_abb |
String input for the state abbreviation to get data for. |
key |
API key for the legacy FBI API (not needed for CDE API). |
A one-row data.frame with columns: state_abbr, total_agencies, nibrs_agencies, participation_rate.
Jared E. Knowles, Civilytics Consulting
Other UCR crime functions:
get_agency_crime(),
get_agency_participation(),
get_leoka(),
get_leoka_monthly(),
get_region_participation(),
get_reported_arson(),
get_reported_crime()
## Not run: get_state_participation("MT") ## End(Not run)## Not run: get_state_participation("MT") ## End(Not run)
Retrieves the list of states/territories from the CDE lookup endpoint.
get_states()get_states()
A data.frame with state abbreviations and names.
## Not run: states <- get_states() head(states) ## End(Not run)## Not run: states <- get_states() head(states) ## End(Not run)
Compares the FBI's estimate for a state or the nation with the crime
agencies reported to the FBI, and says how much of the estimate the
FBI's model supplied. The FBI builds its estimate from NIBRS reports only
and models everything else: agencies that did not report, and agencies
that reported only in the older summary format. So the gap is
measured against reported_nibrs, and reported_other shows the
summary-format reports the model predicted rather than used.
imputation_gap(state_abb = NULL, year, offense = "V")imputation_gap(state_abb = NULL, year, offense = "V")
state_abb |
String for state abbreviation. If |
year |
One or more years, e.g. |
offense |
A summary offense code: |
The API publishes estimates for 2021 and 2022 only (see nibrs_estimation_years), and for states and the nation only. A year it does not cover fails with the API's message listing the years it has.
reported and reported_nibrs differ a little even where every report
arrived in NIBRS, because the two formats count offenses differently
(for example, the summary format counts only the most serious offense in
an incident). In Texas in 2022, where every report did, reported_other
is about -1% of reported_nibrs for violent crime and within about 2%
for every supported offense but burglary (about 6%); vignette("estimates")
gives the table. A reported_other of that size, negative included,
means nearly every report arrived in NIBRS. gap compares two NIBRS
figures, so the counting difference does not enter it, but it is not
exactly zero where little was modeled: for Texas's 2022 violent crime it
is -0.7% of the estimate.
Each row takes one estimate request, one summarized request and one
nibrs request per NIBRS offense code that makes up offense (six for
violent crime).
A data.frame with one row per year:
What was compared
Crime reported to the FBI in either format: the year's
sum from get_reported_crime()
Crime reported in NIBRS only
reported - reported_nibrs: summary-format
reports, plus the counting difference. Can be negative
Mean monthly share of the population covered by agencies reporting in either format
The same, for agencies reporting in NIBRS
The FBI's estimate and the bounds of its confidence interval
published - reported_nibrs: what
the FBI's model supplied, with bounds from the estimate's interval
gap / published: the
share of the published figure the model supplied, with bounds
vignette("estimates") for reported, estimated and imputed
crime.
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
## Not run: # 2021, when the FBI accepted NIBRS reports only imputation_gap("CA", year = 2021:2022) imputation_gap(year = 2021:2022) ## End(Not run)## Not run: # 2021, when the FBI accepted NIBRS reports only imputation_gap("CA", year = 2021:2022) imputation_gap(year = 2021:2022) ## End(Not run)
Fills temporal holes within agencies that report some periods but miss others.
The values it imputes are this package's, from each agency's own
neighboring months, not the FBI's estimate (see get_nibrs_estimate()).
Operates on rate so a drifting denominator is respected: the rate is
linearly interpolated across time (in months), then scaled by the gap
month's own population to derive the imputed count. That is its
participated_population when the CDE reports one, and otherwise its
population: the CDE reports no participated population for a month
the agency did not report, which is every gap. Agencies that never report
in the window, or have no population (e.g. transit or campus police, whose
rate is undefined), are left unchanged. Every filled value is flagged with
imputed = TRUE and impute_method; its
participated_population stays missing, so coverage figures from
get_county_crime() still show the month as unreported.
impute_reporting_gaps(detail, method = "interpolate")impute_reporting_gaps(detail, method = "interpolate")
detail |
A data.frame as returned by |
method |
Imputation method. Currently only |
This is an opt-in transform — the raw detail from get_county_crime_detail()
stays pristine. Call this function explicitly when you need continuous series
for trend analysis. Gaps at the edges (before first or after last reported
period) are not filled; only gaps between known values are interpolated.
A data.frame with the same rows and columns as detail, plus two
new columns:
imputed: logical, TRUE only for rows whose values were
filled by imputation; FALSE for all original (reported or missing)
rows.
impute_method: character, the method name (e.g. "interpolate")
on imputed rows; NA elsewhere.
vignette("estimates") for reported, estimated and imputed
crime.
## Not run: detail <- get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2021") filled <- impute_reporting_gaps(detail, method = "interpolate") table(filled$reported, filled$imputed) ## End(Not run)## Not run: detail <- get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2021") filled <- impute_reporting_gaps(detail, method = "interpolate") table(filled$reported, filled$imputed) ## End(Not run)
Checks if an ORI (Organization Request Identifier) matches the expected 9-character format: 2 letters followed by 7 alphanumerics (letters allowed for state, tribal, campus, and some city ORIs) (e.g. "CA0010900").
is_valid_ori(ori)is_valid_ori(ori)
ori |
Character string or vector of ORI codes. |
Logical vector, TRUE for valid ORIs.
is_valid_ori("CA0010900") is_valid_ori("CA001300X") is_valid_ori("abc123")is_valid_ori("CA0010900") is_valid_ori("CA001300X") is_valid_ori("abc123")
Checks if a state abbreviation is a valid US state or territory code.
is_valid_state(state_abb)is_valid_state(state_abb)
state_abb |
Character string or vector of state abbreviations. |
Logical vector, TRUE for valid state abbreviations.
is_valid_state("CA") is_valid_state("XX")is_valid_state("CA") is_valid_state("XX")
Fetches an American Community Survey (ACS) total-population estimate for each
county represented in detail, keyed by the county_fips column. Returns the
detail frame with an added census_population column (integer). Counties
without a FIPS match or without Census data get NA.
join_census_pop( detail, key = Sys.getenv("CENSUS_KEY"), year = as.integer(format(Sys.Date(), "%Y")) - 2L, dataset = "acs/acs5", census_fun = NULL )join_census_pop( detail, key = Sys.getenv("CENSUS_KEY"), year = as.integer(format(Sys.Date(), "%Y")) - 2L, dataset = "acs/acs5", census_fun = NULL )
detail |
A data.frame as returned by |
key |
Census API key. Defaults to the |
year |
ACS vintage year. Defaults to two years before the current year,
because the ACS 5-year release for year |
dataset |
Census dataset name passed to |
census_fun |
Function used to call the Census API. Defaults to
|
This is an optional feature requiring the censusapi package (in
‘Suggests’) and a free Census API key (set via the CENSUS_KEY
environment variable or the key argument). Without censusapi,
the function returns detail with an all-NA census_population column and
a message.
The default dataset is the ACS 5-year release ("acs/acs5"). The 1-year
release ("acs/acs1") only publishes estimates for geographies of 65,000+
people, which excludes roughly two-thirds of US counties — so 5-year is the
correct default for a county denominator.
The input detail data.frame with an additional census_population
column (integer, one value per county). If censusapi is unavailable
or the request fails, the column is all NA.
## Not run: detail <- get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2019") detail_with_pop <- join_census_pop(detail) agg <- get_county_crime(detail_with_pop, denominator = "census_pop") ## End(Not run)## Not run: detail <- get_county_crime_detail("Alameda", "CA", from = "01-2019", to = "12-2019") detail_with_pop <- join_census_pop(detail) agg <- get_county_crime(detail_with_pop, denominator = "census_pop") ## End(Not run)
Returns every CBSA in the bundled crosswalk, with how many counties each
contains. This is the discovery counterpart to metro_agencies(): it answers
"what may I pass as metro?"
list_metros(type = NULL)list_metros(type = NULL)
type |
Optionally filter to |
A data.frame with columns cbsa_code, cbsa_title, cbsa_type, and
n_counties, carrying the delineation vintage in attr(x, "vintage").
metro_agencies(), counties_with_fips() for the county analogue.
head(list_metros(type = "metro"))head(list_metros(type = "metro"))
variable parameter options for get_nibrs_offender().Returns a vector of all variable parameter options for get_nibrs_offender().
list_nibrs_offender_variables()list_nibrs_offender_variables()
A character vector of all variable parameter options for get_nibrs_offender().
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
list_nibrs_offender_variables()list_nibrs_offender_variables()
variable parameter options for get_nibrs_offense().Returns a vector of all variable parameter options for get_nibrs_offense().
list_nibrs_offense_variables()list_nibrs_offense_variables()
A character vector of all variable parameter options for get_nibrs_offense().
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables(),
list_regions()
list_nibrs_offense_variables()list_nibrs_offense_variables()
List the offense codes the NIBRS functions accept.
list_nibrs_offenses()list_nibrs_offenses()
A data.frame with columns code and label: the summary groups ("V",
"P", "ROB", "BUR", ...) and the NIBRS offense codes from the CDE's
offense lookup. The API also accepts NIBRS offense codes missing from that
lookup, such as "13A" (aggravated assault) or "120" (robbery).
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_victim_variables(),
list_regions()
list_nibrs_offenses()list_nibrs_offenses()
variable parameter options for get_nibrs_victim().Returns a vector of all variable parameter options for get_nibrs_victim().
list_nibrs_victim_variables()list_nibrs_victim_variables()
A character vector of all variable parameter options for get_nibrs_victim().
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_regions()
list_nibrs_victim_variables()list_nibrs_victim_variables()
Return a vector of all regions choices.
list_regions()list_regions()
A vector of all regions choices.
Other NIBRS functions:
get_nibrs_estimate(),
get_nibrs_offender(),
get_nibrs_offense(),
get_nibrs_victim(),
imputation_gap(),
list_nibrs_offender_variables(),
list_nibrs_offense_variables(),
list_nibrs_offenses(),
list_nibrs_victim_variables()
list_regions()list_regions()
get_arrest_count() acceptsThe CDE reports arrests at three levels of detail, and get_arrest_count()
and get_arrest_demographics() accept a name from any of them. Three names
it lists, "Rape", "Rape - Not Specified" and "Runaway", have no
arrests in the API; see
ucr_arrest_offense_codes for the codes behind the rest.
list_ucr_arrest_offenses(level = c("all", "name", "category", "breakdown"))list_ucr_arrest_offenses(level = c("all", "name", "category", "breakdown"))
level |
|
A sorted character vector of offense names.
Other UCR arrest functions:
get_arrest_count(),
get_arrest_demographics(),
get_arrest_demographics_all()
list_ucr_arrest_offenses() list_ucr_arrest_offenses("category")list_ucr_arrest_offenses() list_ucr_arrest_offenses("category")
Resolves a Core Based Statistical Area (CBSA) to the union of its member
counties' agency sets. A metro is a set of whole counties, so this simply
stacks county_agencies() across them, and agency_class keeps exactly
its county-level meaning.
metro_agencies(metro, state = NULL)metro_agencies(metro, state = NULL)
metro |
A CBSA title (e.g. |
state |
Optional two-letter state abbreviation, used only to disambiguate an ambiguous short name. |
CBSA titles are unique nationally, so state is only needed to disambiguate
a short name shared by several metros ("Albany" matches GA, OR and NY).
A data.frame with the county_agencies() columns plus cbsa_code,
cbsa_title, cbsa_type ("metro"/"micro"), and central_outlying
(whether the agency's county is central or outlying in the CBSA). Each ORI
appears once: an agency that polices several member counties is attributed
to the first of them in delineation order, and its agency_county_names
lists all of them. Returns a zero-row frame with a warning when the metro
is unknown.
The bundled crosswalk has 1,915 county-CBSA rows, about 61% of the 3,143
counties and county equivalents known to county_agencies(). That row
count overstates coverage slightly, because Puerto Rico's municipios never
join a CDE county name (see below). Counted as distinct, CDE-reachable
counties instead, coverage is about 58.6% (1,843 of 3,143). Either way,
rural counties belong to no CBSA at all; that is a property of the 2023 OMB
delineation, not a gap in the data.
Connecticut's metros are built from its nine planning regions, the county
equivalents it adopted in 2022, and its agencies are attributed to their
planning region as the CDE reports it (see county_agencies()). Two
Connecticut campus agencies have no region in the CDE's directory, Yale
and UConn Health, so the New Haven and Hartford metros lack them.
Puerto Rico's 10 CBSAs are unmapped, but that is academic: the CDE has exactly one Puerto Rico agency.
Agencies whose county_name is "N/A" – mostly state police, other
state agencies and tribal agencies – cannot be reached from any
county-keyed geography. Three that police a whole county-equivalent are
attributed by the package instead (the NYPD, DC's Metropolitan Police and
the Baltimore City Sheriff; see county_agencies()), so the New York and
Washington metros include them.
list_metros() to discover metro names,
county_agencies().
## Not run: metro_agencies("Pittsburgh, PA") ## End(Not run)## Not run: metro_agencies("Pittsburgh, PA") ## End(Not run)
Built from nibrs-estimation/lookup/all by data-raw/api_vocabularies.R.
get_nibrs_estimate() accepts an id from this table, or one of the
summary codes "V", "P", "ROB", "ASS", "BUR", "LAR", "MVT",
"ARS", "HOM" and "RPE".
nibrs_estimation_indicatorsnibrs_estimation_indicators
A data frame with 71 rows and 3 variables:
The lookup's group: "Person", "Property", "Society"
or "GroupB"
Offense name, e.g. "Violent Crime"
The estimates API's indicator ID, e.g. 133
https://cde.ucr.cjis.gov/LATEST/nibrs-estimation/lookup/all
The estimates API identifies a state by its own number, in roughly
alphabetical order of the postal code (Alaska 1, Alabama 2, California
6), not by FIPS. Built from nibrs-estimation/lookup/all by
data-raw/api_vocabularies.R. The lookup's "Federal" and "Other" entries
have no state abbreviation and are left out.
nibrs_estimation_statesnibrs_estimation_states
A data frame with 57 rows and 3 variables:
Postal abbreviation, as passed to state_abb
Name as the lookup gives it
The estimates API's state ID
https://cde.ucr.cjis.gov/LATEST/nibrs-estimation/lookup/all
Built from nibrs-estimation/lookup/all by data-raw/api_vocabularies.R.
The API publishes estimates for 2021 and 2022 only; a live test fails when
the FBI adds a year, so the package can be rebuilt.
nibrs_estimation_yearsnibrs_estimation_years
An integer vector.
https://cde.ucr.cjis.gov/LATEST/nibrs-estimation/lookup/all
The values get_nibrs_offender() accepts for variable: the keys of a
NIBRS response's offender section. Built by data-raw/api_vocabularies.R.
nibrs_offender_variablesnibrs_offender_variables
A character vector with 4 elements.
https://cde.ucr.cjis.gov/LATEST/
The values get_nibrs_offense() accepts for variable: the keys of a
NIBRS response's offense section. Built by data-raw/api_vocabularies.R.
nibrs_offense_variablesnibrs_offense_variables
A character vector with 2 elements.
https://cde.ucr.cjis.gov/LATEST/
The summary groups ("V", "P", "ROB", "BUR", ...) and the NIBRS
offense codes from the CDE's offense lookup. The API also accepts NIBRS
codes missing from the lookup, such as "13A" or "120". Built by
data-raw/api_vocabularies.R.
nibrs_offensesnibrs_offenses
A data frame with 73 rows and 2 variables:
Offense code, as passed to offense
Offense name
https://cde.ucr.cjis.gov/LATEST/
The values get_nibrs_victim() accepts for variable: the keys of a
NIBRS response's victim section. Built by data-raw/api_vocabularies.R.
nibrs_victim_variablesnibrs_victim_variables
A character vector with 6 elements.
https://cde.ucr.cjis.gov/LATEST/
Resolves a municipality to the agency that reports crime for it. CDE city
agencies are named "<Place> Police Department", so the place name is
recovered from the agency name — the agency is the place. This is an
attribution model, not a spatial one.
place_agencies(place, state, county = NULL)place_agencies(place, state, county = NULL)
place |
Place name (case-insensitive; e.g. |
state |
Two-letter state abbreviation (e.g. |
county |
Optional county name, needed only to disambiguate a place name that occurs in more than one county of the same state. |
Sheriffs, state police, and tribal agencies are never place members: a sheriff's population is the unincorporated remainder, and contract cities report under their own city ORI. A place's crime is therefore carried entirely by its own agency, with no double-count and no gap.
Campus and special-district agencies sit inside places but cannot be
attributed from names alone (name-matching achieves only ~26% recall). Add
them with add_place_spatial_members(), which is opt-in and requires sf
and tigris.
A data.frame with columns ori, agency_name, agency_type_name,
agency_class, place_name, place_type, place_fips, cousub_fips,
county_name, state_abbr, attribution, latitude, longitude.
attribution records how the row earned membership: "name_identity"
here, or "point_in_polygon" for rows added by
add_place_spatial_members(). Returns a zero-row frame (with a warning)
when no municipal agency matches.
Each agency carries the Census code of the unit it polices, for joining Census data:
place_fips: the 7-digit place code (2-digit state + 5-digit place),
when the agency polices a Census place. place_type is then
"incorporated", or "cdp" for the few agencies whose only match is a
census-designated place.
cousub_fips: the 10-digit county subdivision code (state + county +
subdivision), when the agency polices a township, or a New England or New
York town. Those are governments but not Census places; place_type is
then "county_subdivision" and place_fips is NA.
Codes are matched by name within the agency's state, and only among Census
units lying in one of the agency's own counties; an incorporated place wins
over a county subdivision, which wins over a CDP. 98.7% of the 11,646
municipal agencies resolve. The rest – regional and multi-municipality
departments, and two names that match more than one unit in their county –
get NA rather than a guess. Codes follow the Census vintage in
PLACE_VINTAGE; Connecticut's county subdivision codes are therefore the
2020 ones, under its old counties, while Census data from 2022 codes them
under its planning regions.
county_agencies() for the county-level resolver,
get_place_crime_detail() for the crime series.
place_agencies("Lufkin", "TX")place_agencies("Lufkin", "TX")
place_agencies() gives each municipal agency the Census code of the place
or county subdivision it polices, from a crosswalk built from the Census
Bureau's 2020 reference code files (see data-raw/place_fips_crosswalk.R).
Places are occasionally incorporated, merged or dissolved, so codes are
only guaranteed against this vintage. Read from the shipped crosswalk's own
"vintage" attribute when the package loads.
PLACE_VINTAGEPLACE_VINTAGE
An integer scalar.
Some functions let you get regional estimated data and require a string input for which region you want data from. This is a vector of strings for the six regions available.
regionsregions
A vector with 6 elements:
https://cde.ucr.cjis.gov/LATEST/
Deprecated. The current CDE API (cde.ucr.cjis.gov/LATEST/) does not
require an API key. This function is retained only for backward compatibility
with code that previously used the legacy api.data.gov-hosted API.
set_api_key(key)set_api_key(key)
key |
A character string with the API key (ignored). |
NULL. A deprecation message is printed on every call.
## Not run: set_api_key("abc123") ## End(Not run)## Not run: set_api_key("abc123") ## End(Not run)
The CDE's arrest endpoint addresses one offense by numeric code
(arrest/<level>/<code>); an offense name is rejected. Each code is one
breakdown, and reports its arrests under one offense name and one category.
get_arrest_count() and get_arrest_demographics() resolve a name at any
level to its codes and sum them. Built by data-raw/api_vocabularies.R
from the lookup/offenses?type=arrest codes (plus Suspicion, 320, which
the lookup omits), placing each by the names its own response reports.
Three names in ucr_arrest_offenses, "Rape", "Rape - Not Specified"
and "Runaway", have no code and no arrests.
ucr_arrest_offense_codesucr_arrest_offense_codes
A data frame with 47 rows and 5 variables:
The code, as a string
The CDE lookup's label for it
The offense name it reports under
The category it reports under
The breakdown it reports under
https://cde.ucr.cjis.gov/LATEST/
The offense names get_arrest_count() accepts: every key of the three maps
in the CDE's arrest totals response, with the map it comes from. A name can
appear at more than one level. Use list_ucr_arrest_offenses() to list them.
Built by data-raw/api_vocabularies.R.
ucr_arrest_offensesucr_arrest_offenses
A data frame with 112 rows and 2 variables:
Offense name, as passed to get_arrest_count(offense = )
"name" (34), "category" (29) or "breakdown" (49)
https://cde.ucr.cjis.gov/LATEST/