The nycdemog package provides county-, tract-, and block-level
demographic data for the five counties of New York City, derived from
the US Census Bureau via
tidycensus. It provides a set of
tibbles keyed by geoid covering race, age and sex, household
structure, income and poverty, education, employment, housing, and
language and nativity, alongside thin wrapper functions that help you
make NYC-only queries against the Census API.
The tract- and block-level datasets join 1:1 to corresponding sf
objects in the nycmaps package, on
the geoid column. The county-level datasets join to
nycmaps::nyc_boros_sf on the county column, which matches
nycmaps::nyc_boros$short_county_name.
You can install the development version of nycdemog from GitHub with:
# install.packages("pak")
# pak::pak("kjhealy/nycdemog")
install.packages("nycdemog", repos = c('https://kjhealy.r-universe.dev', 'https://cloud.r-project.org'))
The pre-built data tables are in the package. The wrapper functions pull
from the Census API and require you have a Census API
key, set as the
CENSUS_API_KEY environment variable.
Every tibble has geoid and county as its first two columns. ACS
estimates have _moe margin-of-error columns.
library(tibble)
library(nycdemog)
nyc_tract_acs_income_df
#> # A tibble: 2,327 × 16
#> geoid county name med_hhinc med_family_income per_capita_income gini
#> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 36005000100 Bronx Cens… NA NA 3826 NA
#> 2 36005000200 Bronx Cens… 123729 125234 36132 0.377
#> 3 36005000400 Bronx Cens… 105924 140505 37295 0.360
#> 4 36005001600 Bronx Cens… 52147 65353 29200 0.514
#> 5 36005001901 Bronx Cens… 58083 53073 42797 0.502
#> 6 36005001902 Bronx Cens… 48953 NA 24958 0.493
#> 7 36005001903 Bronx Cens… NA NA NA NA
#> 8 36005001904 Bronx Cens… NA NA NA NA
#> 9 36005002001 Bronx Cens… 22311 35461 14873 0.510
#> 10 36005002002 Bronx Cens… 18649 49142 24686 0.539
#> # ℹ 2,317 more rows
#> # ℹ 9 more variables: poverty_total <dbl>, poverty_below <dbl>,
#> # poverty_total_moe <dbl>, poverty_below_moe <dbl>, med_hhinc_moe <dbl>,
#> # gini_moe <dbl>, med_family_income_moe <dbl>, per_capita_income_moe <dbl>,
#> # poverty_rate <dbl>
Full list:
| Object | Source | Geography | Rows |
|---|---|---|---|
nyc_block_20_race_df |
2020 Decennial PL | block | 37,984 |
nyc_block_20_adults_df |
2020 Decennial PL | block | 37,984 |
nyc_tract_20_age_sex_df |
2020 Decennial DHC | tract | 2,327 |
nyc_tract_20_household_df |
2020 Decennial DHC | tract | 2,327 |
nyc_tract_acs_race_df |
2020-2024 ACS 5-year | tract | 2,327 |
nyc_tract_acs_income_df |
2020-2024 ACS 5-year | tract | 2,327 |
nyc_tract_acs_education_df |
2020-2024 ACS 5-year | tract | 2,327 |
nyc_tract_acs_employment_df |
2020-2024 ACS 5-year | tract | 2,327 |
nyc_tract_acs_housing_df |
2020-2024 ACS 5-year | tract | 2,327 |
nyc_tract_acs_language_nativity_df |
2020-2024 ACS 5-year | tract | 2,327 |
nyc_county_20_race_df |
2020 Decennial PL | county | 5 |
nyc_county_20_adults_df |
2020 Decennial PL | county | 5 |
nyc_county_20_age_sex_df |
2020 Decennial DHC | county | 5 |
nyc_county_20_household_df |
2020 Decennial DHC | county | 5 |
nyc_county_acs_race_df |
2020-2024 ACS 5-year | county | 5 |
nyc_county_acs_income_df |
2020-2024 ACS 5-year | county | 5 |
nyc_county_acs_education_df |
2020-2024 ACS 5-year | county | 5 |
nyc_county_acs_employment_df |
2020-2024 ACS 5-year | county | 5 |
nyc_county_acs_housing_df |
2020-2024 ACS 5-year | county | 5 |
nyc_county_acs_language_nativity_df |
2020-2024 ACS 5-year | county | 5 |
get_nyc_acs() and get_nyc_decennial() are thin wrappers around
tidycensus::get_acs() and tidycensus::get_decennial() that hard-code
the five NYC counties, never download geometry, and return a tidy tibble
keyed on a lowercase geoid.
library(nycdemog)
# Median household income, latest 5-year ACS, NYC tracts
get_nyc_acs(c(med_hhinc = "B19013_001"))
# Race and Hispanic origin with total population as the denominator
race_vars <- c(
nh_white = "B03002_003",
nh_black = "B03002_004",
nh_asian = "B03002_006",
hispanic = "B03002_012"
)
get_nyc_acs(race_vars, summary_var = "B03002_001")
# 2020 PL block-level race counts
get_nyc_decennial(
c(nh_white = "P2_005N", hispanic = "P2_002N"),
geography = "block",
sumfile = "pl",
summary_var = "P1_001N"
)
# One row per borough
get_nyc_acs(c(med_hhinc = "B19013_001"), geography = "county")
Use load_nyc_variables() to browse the variable catalogues:
load_nyc_variables(2024, "acs5")
load_nyc_variables(2020, "pl")
load_nyc_variables(2020, "dhc")
Every stored tract- or block-level tibble joins on geoid to the
matching sf object in nycmaps; the county-level tibbles join to
nycmaps::nyc_boros_sf on county. Mapping median household income
across NYC tracts:
library(dplyr)
library(ggplot2)
library(sf)
library(nycmaps)
nyc_census_tracts_2020_sf |>
inner_join(nyc_tract_acs_income_df, by = "geoid") |>
ggplot(aes(fill = med_hhinc)) +
geom_sf(color = NA) +
scale_fill_viridis_c(
option = "magma",
labels = scales::label_dollar(),
na.value = "grey90"
) +
labs(fill = "Median\nhousehold\nincome") +
theme_void()

–
Hex photo: Detail from Terry from Sydney, “New York City 1979”.