Rubber meets road / Summer youth employment
How I built this
Every step that turns public data into this map, and every judgment call along the way: what was decided, why, what the alternative was, what difference it makes and who made the call. The methodology page has the formulas; this page is about the choices.
Who did what. Josh Greenman set the goal (a two-measure map to weigh where New York City's Summer Youth Employment Program could do more), chose the core factors (young people, crimes involving young people, poverty), and made the calls marked Josh. Anthropic's Claude, working in Claude Code, wrote the code, pulled and processed the data, and made the calls marked Claude; those are listed so they can be reviewed and changed. Calls marked Carried over come unchanged from the two tools this one is built from, the New York City population explorer and The summer jobs gap.
On this page
1. The build, step by step
Four Python scripts produce the data files; the page itself is plain HTML and JavaScript that reads them. Everything runs from public sources, and every pull checks itself and stops rather than writing an empty or implausible file. Source code: github.com/Vital-City-NYC/syep-factor-map.
- Find NYPD's station houses (
fetch_youth.py). Read the address on each of the 78 precinct pages on nyc.gov, geocode each with NYC Planning's GeoSearch, and confirm the ZIP code matches. Add the 40th Precinct's former building. Saved todata/stations.jsonwith the page each address came from. - Pull 2024 arrests of people under 18 and 18 to 24 from NYPD's arrest file, keeping NYPD's own jurisdictions. The script first counts how many 2024 arrests lack an age and stops if it is more than 2%.
- Pull shootings from July 2023 through June 2026 with their suspects and victims (three NYPD tables joined on the incident number), fixing swapped coordinates.
- Pull violent crimes against young people: murders, robberies and felony assaults with a victim under 25, July 2025 through June 2026 by report date. Stops if more than 8% lack a victim age.
- Place every NYPD record in a census tract (
nypd_places.py). A record within 140 meters of its own precinct's station house is left out. Every other record is assigned by its point; a point on a tract boundary is shared equally among the tracts that meet there. - Pull the summer program sites from the Department of Youth and Community Development (DYCD), keep the latest fiscal year, drop year-round programs and keep one entry per location. Count sites in each tract and within a mile of each tract.
- Pull the 2020 census count of residents aged exactly 14 through 24 for every tract.
- Split tracts along precinct lines and count every NYPD record by precinct (
fetch_precincts.py, added Oct. 9). Pull City Planning's precinct boundaries and all 37,984 census blocks with their 2020 populations; place each block in a precinct; record what share of each tract's residents lives in each precinct. Count every arrest, shooting and violent crime by the precinct NYPD assigned it, for the same windows, and stop unless the totals match the neighborhood pull. - Pull the major-felony counts (
fetch_crime.py), placed by the same rules. Since Oct. 9 they feed only the caveat on areas with large daytime crowds. - Pull the survey data and build every measure (
build.py): American Community Survey (ACS) 2020–24 tables for every tract from Census Reporter, a check that every table cell carries the label the Census Bureau gives it, every measure derived for tracts and then for neighborhoods and precincts (summing the underlying counts, never averaging rates; precincts take each tract's share), a check that precinct sums equal the city totals, and the files the page reads, which carry only the 25 measures the map offers. - Check the preset explanations (
scripts_check_presets.py): every place and borough the text names must sit in the part of the grid the text describes, in both views, and every quoted correlation must match.
2. Judgment calls
What the map is
Two measures at once, with every measure selectable
- Decision
- The default view colors each area by two measures, and any measure can go on either axis.
- Why
- Requested: a two-measure map with the youth factors selectable.
- Decided by
- Josh
25 measures about young people, not 96
- Decision
- The menu offers only the young-people, need, arrests and violence measures plus summer jobs sites within a mile: 25 in all.
- Why
- The first version carried over all 69 measures from the population explorer (race, housing, elections and more), which buried the youth measures the map exists for.
- Effect
- 71 measures removed, including the count of sites located inside an area; the remaining values are unchanged.
- Decided by
- Josh, Oct. 9
No combined score
- Decision
- The map never folds measures into an index or ranking.
- Why
- Any index embeds weights that are themselves judgment calls. The companion tool, The summer jobs gap, offers an explicit need index with adjustable weights; this one keeps each measure separate so the reader sees what drives a pattern.
- Alternative
- A weighted need score per neighborhood.
- Decided by
- Claude
Police precincts by default, neighborhoods one click away
- Decision
- The map opens on NYPD's 77 precincts plus Central Park; a switch shows City Planning's 262 neighborhoods.
- Why
- NYPD logs a quarter of youth arrests and one in eight shootings at a precinct station house, with no street location. A precinct map can count every one of them by the precinct NYPD assigned; a neighborhood map has to leave them out, because a precinct overlaps a median of four neighborhoods and as many as ten.
- Alternatives
- Neighborhoods only (finer areas, about 43,000 residents each, but missing those records); precincts only.
- Effect
- The default view counts 9,450 under-18 arrests in 2024, against 6,296 placed in neighborhoods. Precincts average about 110,000 residents and blur differences within them.
- Decided by
- Josh, Oct. 9
No tract view
- Decision
- The census-tract view the first version offered was removed.
- Why
- Tract estimates of small youth groups are too noisy to rank; combining about nine tracts cuts a typical margin of error to roughly a third. Removing tracts did not by itself let the map count station-house records (see above).
- Decided by
- Josh, Oct. 9
Census tracts split along precinct lines by 2020 block population
- Decision
- Each tract's survey figures are divided among precincts in proportion to where its residents lived in the 2020 census, block by block. Margins of error for the split pieces are scaled by the same shares.
- Why
- Tract lines usually follow precinct lines but not always: 160 of 2,327 tracts have less than 95% of their residents in one precinct. Blocks are small enough to place exactly.
- Alternatives
- Split by land area (worse where people live unevenly, as next to parks); give each tract wholly to the precinct holding its center (simpler, but misplaces part of 160 tracts).
- Effect
- Precinct totals equal the city totals exactly. Figures for split tracts assume 2020 residence patterns still hold; their margins of error are slightly understated.
- Decided by
- Claude
Parks, cemeteries, airports, bases and jails get counts but no rates
- Decision
- City Planning classifies 65 neighborhood areas as non-residential. They keep counts (people, arrests, sites) but show no shares, medians or rates.
- Why
- The few people counted there live mostly in places like Rikers Island and Fort Hamilton, and their percentages swing wildly (Miller Field, with 75 residents, came out 85% Hispanic and was setting the top of a color scale).
- Decided by
- Carried over (from the population explorer's Oct. 8 review)
Ages
16 to 24 for poverty, work and population
- Decision
- Most youth measures use ages 16 to 24, though the program serves 14 to 24.
- Why
- The survey's small-area tables on employment start at 16 and break poverty at 15, 16 and 18; 16 to 24 is the widest band every measure can share. The exact 14-to-24 count exists only in the 2020 census, which is included as its own measure.
- Effect
- 14- and 15-year-olds, who are eligible, are missing from most measures.
- Decided by
- Carried over (The summer jobs gap uses 16 to 24)
"Under 24" becomes 24 and younger
- Decision
- Arrests, shootings and violence measures use "under 25," meaning 24 and younger.
- Why
- NYPD records age only in bands (under 18, 18 to 24, 25 to 44 and so on), so there is no way to stop at 23.
- Decided by
- Claude, forced by the data
Teens out of school and work: 16 to 19 only
- Decision
- The "disconnected youth" measure covers 16- to 19-year-olds.
- Why
- It is the only age range the Census Bureau publishes for small areas (table B14005).
- Decided by
- Carried over
Arrests
2024, not 2025
- Decision
- Arrest measures use calendar 2024.
- Why
- NYPD's 2025 file has no age on 147,237 of 278,953 arrests (52.8%), unevenly by borough (61% in the Bronx, 34% on Staten Island). Using it would make youth arrests look half as common, and differently so by place. 2024 has an age on every arrest.
- Alternative
- January–June 2026, which is complete but only six months. It was used as a check instead: the 2024 neighborhood pattern correlates with it at 0.86 (under 18) and 0.96 (18 to 24).
- Decided by
- Carried over (The summer jobs gap made the same call)
NYPD's own arrests only
- Decision
- Keep arrests under NYPD's patrol, transit and housing jurisdictions; leave out the 1,223 youth arrests (2.3%) recorded under other agencies.
- Why
- Most of the others sit at a single Hunts Point point under one agency code, mostly for offenses against public administration and felony assault, the profile of arrests of people already in custody. They doubled the Hunts Point neighborhood's 18-to-24 arrest rate.
- Alternative
- Keep all agencies, or drop only that cluster (which would require knowing exactly what the site is).
- Decided by
- Claude
Counted where the arrest happened, compared with residents
- Decision
- Arrest rates divide arrests made in an area by the young people who live there (per 1,000 residents aged 10 to 17, 18 to 24 or 10 to 24).
- Why
- NYPD publishes no home address, so there is no residence-based arrest count for small areas. The age-matched denominator is the closest available comparison.
- Effect
- Areas that draw young people from elsewhere run high. Midtown, with few resident children, has the highest under-18 rate by far; the page flags heavy daytime areas.
- Decided by
- Claude
No rate where fewer than 100 people are in the age group
- Decision
- Arrest, shooting and violence rates are blank where the matching age group has fewer than 100 residents; counts are still shown.
- Why
- A single arrest among 30 teenagers would read as 33 per 1,000.
- Decided by
- Claude
Where NYPD records go on the map
Records without a street location are left out of the neighborhood view
- Decision
- Records NYPD logs at a precinct station house are not counted in any neighborhood. No record is assigned to a neighborhood by its precinct. The precinct view, added Oct. 9, counts them by the precinct NYPD assigned.
- Why
- NYPD's own footnote says arrests it cannot geocode are placed at the station house; nearly every rape complaint is placed there too, to protect victims, and so are about one in eight shootings involving young people. Those records have no known location.
- Alternatives
- (1) Leave them at the station house, which piles a precinct's worth into one tract (up to 95 extra violent felonies a year in some). (2) Spread them across the precinct in proportion to its other records, which an earlier version of this map did; that counts them in neighborhoods by estimate.
- Effect
- Neighborhood counts understate: 33% of under-18 arrests and 23% of 18-to-24 arrests are left out, from 15% to 44% depending on the precinct. Shootings with a young suspect lose 12%; young shooting victims 13%; violent crimes against young people 2%. The violent-crime rate from the population explorer now counts very few rapes.
- Decided by
- Josh
How station-house records are recognized
- Decision
- A record within 140 meters of its own precinct's station house counts as placed there. The 40th Precinct's old building at 257 Alexander Avenue counts too.
- Why
- NYPD's station point and the geocoded address differ by tens of meters. The radius was set from the data: in 75 of 76 precincts, the biggest stack of 2024 arrests spanning many offense types sits within 140 meters of the station address (the exception is the 14th Precinct, where Macy's Herald Square is the bigger stack). The 40th Precinct moved in late 2024, but NYPD still places its records at the old building.
- Effect
- A real incident within 140 meters of a station house is also left out.
- Decided by
- Claude
Records on a boundary are shared
- Decision
- A record within 10 meters of a tract boundary is split equally among the tracts that meet there.
- Why
- NYPD places each record at an intersection or mid-block on the street centerline, and most tract and neighborhood boundaries run down street centerlines. Which side a record lands on would otherwise depend on hairline differences between two sets of map lines. 52% of street-located youth arrests are shared this way, and about one in five sits on a line between two neighborhoods.
- Effect
- Counts can be fractional; a busy boundary street's arrests are divided between the neighborhoods on either side instead of all going to one.
- Decided by
- Claude, approved by Josh
Shootings and violence
Three years of shootings, as a yearly rate
- Decision
- Shooting measures pool July 2023 through June 2026 and divide by three.
- Why
- Shootings have fallen sharply (974 in 2023, 688 in 2025); a single year leaves most neighborhoods at zero or one.
- Decided by
- Claude
"Suspect," not "shooter"
- Decision
- The measure counts shootings in which NYPD lists at least one suspect under 25.
- Why
- NYPD's offender table lists people it identified or described, not people convicted, and has no entry for 38.6% of shootings. The description says it undercounts.
- Decided by
- Claude
Violence measured by the victim's age
- Decision
- "Violent crimes against people under 25" uses the victim's recorded age, for murder, robbery and felony assault.
- Why
- NYPD complaints record a victim age 95% of the time; the suspect's described age is missing on about 47%, so a "crimes by young people" measure built from complaints would be mostly guesswork. Rape is left out because its location is withheld.
- Alternative
- Complaints by the suspect's described age, the closest match to the original question (crimes committed by young people). Arrests and shooting suspects stand in for it.
- Decided by
- Claude
Report date, not occurrence date
- Decision
- Complaints are dated by when they were reported (
rpt_dt). - Why
- That is NYPD's own reporting convention and a standing rule for Vital City's crime work.
- Decided by
- Josh (standing rule)
Summer program sites
Sites, not slots or jobs
- Decision
- Supply is measured by DYCD's program sites for summer 2025: 122 locations after dropping year-round programs and duplicate rows.
- Why
- DYCD publishes no slot counts by site and no list of the employer worksites where participants work. Sites show where the program has a presence, not how many young people it serves there.
- Decided by
- Carried over (same rules as The summer jobs gap, which also finds 122)
"Within a mile" from a point inside each tract
- Decision
- For each tract, count sites within one mile of the Census Bureau's internal point; for a neighborhood or precinct, average its tracts' counts, weighted by residents 16 to 24.
- Why
- Young people use sites across neighborhood lines; a count of sites inside a neighborhood's borders would treat a site across the street as absent. Weighting by young residents reflects what a typical young person has nearby.
- Alternative
- The summer jobs gap's two-step method, which also divides each site among all the young people who can reach it. This map keeps the simpler count. A count of sites inside each area was also offered until Oct. 9.
- Decided by
- Claude chose the method; Josh chose to keep only this site measure (Oct. 9)
Survey data
Neighborhood medians computed from income brackets
- Decision
- Neighborhood medians (income, age, rent, home value, rent burden) are interpolated from the combined bracket counts of their tracts, the method City Planning uses.
- Why
- The earlier approach, averaging tract medians, was off by up to $28,000 on income. The new method matches City Planning's published neighborhood figures within $2.
- Decided by
- Carried over (from the population explorer's Oct. 8 review)
How the map shows things
Thirds, not equal intervals
- Decision
- Each measure is split into thirds (low, middle, high) across the areas that have both values; a value tied with a cut point goes to the lower third.
- Why
- Thirds give each color a similar number of areas and keep extreme values from washing out the map. The legend prints the cut points and how many areas fall in each third, because ties (lots of zeros, for instance) can make the thirds uneven.
- Effect
- "High" means high relative to other New York City neighborhoods, not high by any outside standard.
- Decided by
- Claude
The seven ready-made comparisons
- Decision
- Seven pairings framed as investment questions (need against nearby sites, violence against nearby sites, and so on), each with a short explanation that names places.
- Why
- To give readers a way in. Each has two explanations, one for precincts and one for neighborhoods, written from the data and tested by code.
- Decided by
- Claude; not yet reviewed by Josh
Design
- Decision
- Vital City's design system (Halyard type, black hairlines, no rounded corners), the "Rubber meets road / Summer youth employment" kicker and the same two-way palette as The summer jobs gap (blue across, magenta up, plum where both are high).
- Decided by
- Josh asked for Vital City style; Claude chose the details to match the companion tool
3. How the numbers were checked
- Census labels. The build stops if any of the 113 table cells behind the youth measures carries a different label than expected.
- City Planning's tables. Children under 18 and residents under 25 match in all 262 neighborhood areas; child poverty matches in all 197 residential ones; medians match within $2.
- Totals. Arrests, shootings, violent crimes and program sites reconcile with counts queried directly from NYC Open Data. The precinct view's sums equal them exactly; the neighborhood view's equal them minus the station-house records left out. Precinct residents add up to the city total, 8,483,844.
- Independent recomputation. A separate check, written from scratch, recomputed ten neighborhoods from the Census Bureau's and NYC Open Data's own interfaces: every survey value, 2020 count, total and rate matched. It caught a distance formula that ran 0.26% long and three wording problems, all fixed.
- Preset text. Every place, borough count and correlation named in the 14 explanations (seven per view) is checked against the data by a script.
- Browser testing. Shared links, both geographies, both modes, the menus and phone-width layout were tested in a browser before publishing.
4. What changed after the first version
The map was first published on Oct. 8, 2026, and changed the same day:
- Arrests limited to NYPD's own jurisdictions, after the Hunts Point cluster turned up.
- Fixes from the independent recomputation: a more precise distance formula and clearer descriptions.
- Station-house records left out instead of spread across the precinct (Josh's call).
- Records on a boundary shared among the areas that meet there.
- Arrests of everyone 24 and younger added as one measure.
- The measure menus moved to the top of the page, labeled "across" and "up," searchable, with a swap button and a list of ready-made comparisons.
On Oct. 9, 2026, at Josh's direction:
- Police precincts became the default view, counting every arrest, shooting and violent crime, including those NYPD logs at a station house; neighborhoods remain one click away.
- The census-tract view was removed.
- The menu was cut from 96 measures to the 25 about young people and summer jobs sites within a mile.
- The companion link to the old research table was replaced with Vital City's evidence browser.
5. What the map does not do
- It does not say where young people who are arrested or shot live. No public small-area data records that.
- It does not show crimes committed by young people. Arrests and shooting suspects are the closest public measures, and both reflect police activity.
- It does not include the city's youth detention admissions, which are published only by community district, a different geography.
- It does not measure program capacity. DYCD publishes no slots by site.
- It does not rank areas or recommend where to invest. It shows where measures coincide.
- It does not place station-house records in neighborhoods; only the precinct view counts them.