← Back to map

Methodology & sources

How this map was built, what every variable means, and what its limits are.

Data sources

Geography

All five New York City boroughs at the 2020 census tract level — 2,325 tracts in total. A tract is a small statistical area that typically contains 1,200–8,000 people. Tract boundaries are stable enough to compare across years but small enough to surface meaningful neighborhood-scale differences.

The "Borough" and "NTA" (Neighborhood Tabulation Area) labels in the detail panel come from NYC DCP's official 2020 designations. Tracts that fall in parks, cemeteries, airports, or industrial areas may show small or zero population.

How values are calculated

Every variable in the map either comes directly from an ACS estimate (medians and totals) or is computed as a share, using the denominator the Census Bureau publishes alongside that table. For example:

Full variable list

FieldSource table / formula
Total populationB01003_001
Population densityB01003_001 ÷ tract land area (sq mi)
Median ageB01002_001
Share under 18Σ B01001 male+female under-18 cells ÷ B01003_001
Share 65 and overΣ B01001 male+female 65+ cells ÷ B01003_001
White, Black, Asian (non-Hispanic), HispanicB03002_003 / 004 / 006 / 012 ÷ B03002_001
Median household incomeB19013_001
Household income bandsSums of B19001 cells ÷ B19001_001
Poverty rateB17001_002 ÷ B17001_001
Receiving SNAPB22010_002 ÷ B22010_001
Households / avg household sizeB11016_001 / B25010_001
Owner-occupied homesB25003_002 ÷ B25003_001
Median gross rent / home valueB25064_001 / B25077_001
Median rent burdenB25071_001 (median rent as % of household income)
Bachelor's+ / HS onlyΣ B15003_022–025 / Σ B15003_017–018 ÷ B15003_001
Foreign-bornB05002_013 ÷ B05002_001
Not a U.S. citizenB05002_021 ÷ B05002_001
Non-English at home(C16001_001 − C16001_002) ÷ C16001_001
In labor force (16+)B23025_002 ÷ B23025_001
Commute mode sharesB08301_010 / 019 / 021 ÷ B08301_001
Veterans (18+)B21001_002 ÷ B21001_001
Unemployment rateB23025_005 ÷ B23025_003 (BLS-standard: unemployed ÷ civilian labor force, not ÷ total labor force)
No home internetB28002_013 ÷ B28002_001 (no subscription and no other internet access at the residence; households with free access but no subscription are in B28002_012 and are not counted here)
Households with no vehicle / 2+ vehiclesB08201_002 / Σ B08201_004-006 ÷ B08201_001
Average vehicles per householdΣ (bucket midpoint × bucket count) ÷ B08201_001 (4+ bucket treated as 4.5)
Homeowners / renters without a vehicleB25044_003 ÷ B25044_002 / B25044_010 ÷ B25044_009
K-12 students in public / private school (by residence)Σ B14002 K-12 public (or private) male + female cells ÷ total K-12 students. Tracks where the students live.
Public-school K-12 enrolled (by school location)Σ DOE Demographic Snapshot enrollment by school (latest year), aggregated to the tract containing each school's address. Tracks where the schools are.
Major-felony rate(Σ NYPD complaints with KY_CD ∈ {101, 104, 105, 106, 107, 109, 110}) ÷ population × 1,000
Violent-crime rate(Σ NYPD complaints with KY_CD ∈ {101, 104, 105, 106}) ÷ population × 1,000
Property-crime rate(Σ NYPD complaints with KY_CD ∈ {107, 109, 110}) ÷ population × 1,000

Election details

Vote shares are reported as the candidate's share of major-candidate votes — not of all ballots cast. For the presidential races and the 2021 mayoral race, this means D ÷ (D + R), so the values are directly comparable across years even when third-party candidates differ. For 2025 mayoral, the denominator is Mamdani + Cuomo + Sliwa (the three major candidates); minor candidates are not counted in the denominator.

Each candidate's vote total includes all of their ballot lines. Biden 2020 counts Democratic + Working Families; Harris 2024 counts Democratic + Working Families; Trump 2020 and 2024 count Republican + Conservative; etc. Cross-endorsed ballot lines are summed because they represent votes for the same candidate.

NYC redrew Election District boundaries after the 2020 redistricting cycle, so 2020/2021 results use the pre-redistricting ED geometry (~5,700 EDs) and 2024/2025 results use the post-redistricting geometry (~4,070 EDs). Both are aggregated to the same 2020 census tract boundaries. Because EDs are typically much smaller than tracts (~2–3 EDs per tract on average), the centroid-based join is reliable.

Tracts with fewer than 25 total major-candidate votes for a given election are suppressed (shown as "no data") for that election, because vote shares from tiny samples are noisy.

Rent-stabilized units — how the unit count is derived

NYC's official rent-stabilization registry, maintained by the state's Division of Housing and Community Renewal (DHCR), does not publish unit counts per building. The annual Rent Guidelines Board lists released by NYC RGB are PDFs of building addresses only — no unit data.

The numbers on this map come from a workaround that exploits NYC's tax system. The Department of Finance charges every rent-stabilized building an annual per-unit "Rent Stabilization Fee" on its property tax bill (recently $15 per registered unit, plus a flat administrative charge). The fee line item appears on the property's annual DOF Statement of Account PDF. Divide that fee by the per-unit rate and you've reverse-engineered the registered unit count for that building. The JustFix.nyc team's nyc-doffer project scrapes every NYC tax lot's Statement of Account PDFs annually, extracts the fee, and publishes per-BBL unit counts back to 2018. That's what's aggregated to tracts here.

What the unit counts actually mean and don't mean:

Crime rate details

NYPD's "seven major felonies" (sometimes called Index 7) are the historical FBI Part I categories the department reports for CompStat. We split them into the two standard buckets:

Each complaint is filed to the date the incident was reported to police (RPT_DT), not the date it allegedly occurred — that's the field NYPD uses for its own performance reporting, and the only one that's reliably populated.

Complaints are placed on the tract map by point-in-polygon on the NYPD-reported latitude/longitude. The denominator is total population from the same ACS table used elsewhere on this page (B01003_001), so the rate is per 1,000 residents, not per 1,000 daytime population or per 1,000 visitors. Tracts with fewer than 50 residents (parks, cemeteries, airports, transit yards) are shown as "no data" on the rate maps because the denominator is too small to be meaningful — a single felony in a 12-person tract would produce an 83-per-1,000 rate.

The "rolling 12 months" window spans the most recent 365 days for which combined data are available. Because the Historic dataset is updated quarterly and the YTD dataset daily, this can shift forward each time the build script is re-run.

Margins of error and reliability

ACS is a sample, not a count. Every cell estimate comes with a margin of error (MOE) at 90% confidence. For tracts with small populations or small subgroups, the MOE can be a substantial fraction of the estimate itself — sometimes larger than the estimate. We surface this in three places:

MOEs for derived shares are propagated using the Census Bureau's standard formulas from the ACS General Handbook (Appendix 3): moe(p) = √[moe(x)² − p² · moe(y)²] / y for proportions where the numerator is a subset of the denominator (with a fall-back to the independent-ratio formula when the radicand is negative). Sum-of-cells MOEs use √Σmoe². Medians use the published MOE directly.

The undocumented-population proxy

The U.S. Census Bureau does not ask about immigration status, so there is no direct tract-level count of undocumented residents. Every published "undocumented by tract" figure is a model output, not a measurement. The closest publicly available variable that gets at this population without modeling assumptions is B05002_021 — "Foreign-born, not a U.S. citizen." We surface it as "Not a U.S. citizen."

This variable over-counts the undocumented population because it also includes:

Calibrating it to undocumented requires a multiplier. National estimates (Pew, MPI, CMS): roughly a quarter of all foreign-born residents are undocumented. For NYC specifically, the Center for Migration Studies estimates roughly a third of non-citizens are undocumented, and the share varies by country-of-origin neighborhood (lower in Soviet-era Russian-speaking enclaves, higher in some Latin American and West African corridors). A tract with 1,000 "Not a U.S. citizen" residents likely contains around 300–400 undocumented residents, with substantial neighborhood-level variation.

This map does not multiply by that factor — we show the raw proxy and ask the reader to understand it as such. CMS publishes more authoritative estimates at sub-city geographies (Community District level); when this map grows a Community District aggregation, those will be layered in directly.

What is not yet here

Color scales

The map offers two binning options for every variable:

Each thematic group uses a different single-hue palette to make the active variable immediately recognizable.

Known limits

The American Community Survey is a sample, not a census. At the tract level — especially for small subgroups in low-population tracts — margins of error can be large. Treat single-tract values as estimates with uncertainty, not as exact counts.

Reproducing this map

The Python build script (build.py) fetches all ACS variables from Census Reporter, joins them to NYC DCP tract geometry, computes the derived shares, and writes tracts.geojson and variables.json into the docs/ folder. The page is plain HTML/JS — Leaflet for the map, d3 for color scales, no build step. Source is available on GitHub.

← Back to map