Part 6 of 9 in After You Call: A Deep Dive on Philly 311
Income Explains 19% of Philly's 311 Wait Times. The Other 81% Doesn't Care About Income.
Income tier predicts only 19% of Philadelphia 311 wait times. The other 81% is zip-by-zip — Fairhill outpaces higher-tier zips; Elmwood waits 17.9 days.
Each dot is a Philadelphia zip code. The zero line is what its 311 wait time should be based on income alone — orange dots wait much longer than that, blue dots wait much less.
This is the relationship between income and 311 wait times in Philadelphia, all 43 zip codes with at least 1,000 closed tickets — with one twist on a normal scatter plot. The y-axis is not the raw wait time. It is the residual: the gap between how fast a zip actually closes its 311 tickets and how fast a simple income-only regression predicts it should.
The horizontal line at zero is what income alone says the zip should deliver. Dots below the line close faster than income predicts. Dots above close slower. The red band on the left marks lower-tier zips (under $35,000 median household income); the green band on the right marks higher-tier zips (over $70,000).
If income fully explained 311 wait times, every dot would sit on the line. Most of them do not. The line's R² is 0.19 — income predicts 19% of the variance. The other 81% is the residual, and the residual is what this article is about. Look at the labels: 19142 Elmwood sits almost ten days above the line (9.2 days slower than its $32,100 median income would predict); 19133 Fairhill sits 3.9 days below (faster than its $30,200 median income would predict). Same income band, same city, opposite sides of the chart by thirteen days.
Heads-up. This article is more technical than most of what I write — terms like regression, residuals, and OLS appear in the body. I usually avoid math like this on my blog, but I needed it here. The finding is that even after controlling for income, Philadelphia zips wait wildly different amounts of time for 311 service, and the within-tier variation is bigger than the income gap itself. There is no way to demonstrate that without the regression machinery. I have defined each technical term in plain English the first time it appears, and the chart captions are written for the casual reader.
The within-tier spread
The income-tier story is real. Lower-tier zips wait 7.1 days at the median; higher-tier zips wait 4.7 days; the gap is 2.4 days. The chart above is the visual version of what that population average hides — 43 dots scattered across an income axis, most of them at least a couple of days away from the line, the labeled outliers farther still.
Lower-tier zips range from 4.8 to 17.9 days — the fastest matches the higher-tier median, the slowest is more than three times slower. The within-tier range is over five times the between-tier gap. The income-tier average is the wrong unit of analysis for both ends of the lower-tier range.
I fit a single-variable OLS regression to separate the income effect from everything else: median_days = 10.8 + (−6.6 × 10−5) × median_household_income. R² is 0.19 — income explains 19% of the variance, and the other 81% is the residual: the gap between what the line predicts and what each zip actually delivers.
The point of the residual analysis is to separate the income effect from everything else. A zip with a 9-day positive residual is being failed by something other than its income. A zip with a 4-day negative residual is being served by something other than its income. The labels of those somethings — agency, geography, chronic-corner concentration, dispatch routing — are what the income-tier analysis cannot see.
The bright spots
The chart’s top bright residual is 19122 Norris Square, but I’m not going to build the article around it. Norris Square is one of the most rapidly gentrifying zips in Philadelphia — heavy new construction, a population that has turned over fast enough that the ACS five-year median income lags the actual median resident, and a tier of new residents who know how to file a 311 ticket with a tight address and a photo attached. The bright residual is real; the “a low-income zip is being well-served” framing is not. So the example I want to anchor on is the next one down the list.
19133 — Fairhill — $30,200 median income, 8,284 closed tickets, 4.9-day median close. The income-only model predicts 8.8 days; the actual is 3.9 days below — the second-largest negative residual in the city, and the largest one whose income figure is not a gentrification artifact. This is a dense, row-house neighborhood at the bottom of the income distribution that delivers higher-tier 311 speeds.
The most plausible mechanism is civic infrastructure. Fairhill is dense, and dense neighborhoods automatically get the operational benefits — low marginal cost per ticket, route-level local knowledge — but those benefits only show up when residents actually file accurate, well-addressed, repeatable tickets. The block captains, tenant unions, and neighborhood groups are the multiplier. I have watched this in Fairmount, where I live: the same neighbors who run the community garden are the ones who file 311 tickets with the right address format, a photo attached, and a follow-up call a week later. The system responds because the system knows the people calling. The city should be studying Fairhill. As far as I can tell, it is not.
The dark spots
The dark spots are where the within-tier story turns into a story about specific blocks of Philadelphia being systemically neglected on top of the income-tier penalty.
19142 — Elmwood — $32,100 median income, 7,422 closed tickets, 17.9-day median close. The income-only model predicts 8.7 days. The actual is 9.2 days above the prediction. The 90th-percentile close time is 172.4 days — nearly six months. The mean is 57.3 days. Elmwood is the single most under-served zip in Philadelphia by residual analysis, and it is under-served by a margin of nearly ten days. There is no other lower-tier zip within five residual days of it.
19153 — Eastwick — $32,800 median income, 3,423 closed tickets, 16.4-day median close. Residual +7.8 days. The 90th-percentile is 174.5 days. These two zips are physically adjacent, on the southwest edge of the city, next to Philadelphia International Airport. They are also the most transit-isolated parts of the city. The mechanism is dispatch geography: the two worst-residual zips in the lower tier are the two zips furthest from center-city Streets Department operations. A crew dispatched from a central yard spends more time in transit, closes fewer tickets per shift, and competes with closer tickets for the same crew-hours. Eastwick sits at the end of every route, and the route never quite reaches it.
The other three in the top-5 dark spots are: 19135 — Tacony (middle tier, $38,900 income, 15.8-day median, +7.6 days residual); 19111 — Fox Chase (middle tier, $42,300 income, 12.3-day median, +4.3 days residual); and 19124 — Frankford (lower tier, $34,700 income, 12.3-day median, +3.8 days residual). All three are far Northeast, separated from center city by the river and by the I-95 corridor. The geographic pattern of the dark spots is not a coincidence.
One more thing I expected to find
I expected the chronic-complaint rate to track the income gap. I was wrong. Higher-income zips have a higher chronic-complaint rate per 1,000 tickets than lower-income zips. The numbers: 14.0 chronic (address, service) pairs per 1,000 tickets in the higher tier (711 pairs across 9 zips, 50,842 tickets); 11.5 in the lower tier (1,964 pairs across 14 zips, 170,951 tickets); 10.9 in the middle tier (2,174 pairs across 20 zips, 200,017 tickets). The citywide median is 11.0.
The mechanism is re-reporting behavior, not neglect. The chronic-pair definition is mechanical — a (rounded address, service-type) pair with at least 5 reports spanning a year — and it counts the same physical corner whether the call comes from a homeowner who files weekly or a tenant who files once and gives up. Higher-income residents keep calling when the city does not respond; lower-income residents stop calling and route around the system. The chronic-pair rate is 14.0 in higher-tier zips not because those zips are neglected more, but because their residents have the time, the patience, and the expectation that someone will eventually answer the phone.
The chronic-failure rate is not the same thing as the median-wait rate, and the within-tier analysis of this article is mostly about the median. The chronic-pair analysis is a side-finding — the kind of thing you notice when you are pulling on a thread and the thread turns out to have a second thread attached. Both threads are real. They are not the same thread.
What the within-tier variance implies
The 2.4-day “income gap” headline from the parent article is a population average. It is the right number to cite when you are comparing the lower tier to the higher tier as a whole. It is the wrong number to cite when you are talking to a resident in Eastwick or Fairhill.
For the Elmwood resident, the relevant number is 17.9 days — not 7.1. The income-tier average understates the Elmwood experience by 10.8 days, or 2.5×. For the Fairhill resident, the relevant number is 4.9 days — not 7.1. The income-tier average overstates the Fairhill experience by 2.2 days. The income-tier average is the wrong unit of analysis for both of them.
The right policy unit, for the residents who actually live in these zips, is the zip. Elmwood needs an operational intervention, and it is not an income-tier intervention — it is a zip-specific intervention. The same is true, in the opposite direction, for Fairhill: someone inside city government should be asking what that zip is doing right, and trying to replicate it.
I am not arguing the income gap is a distraction. The income gap is real, and the 19% of variance that income explains is the largest single lever in the data. But 81% of the variance is something else, and the something else is bigger. That is the part the income-tier story hides, and the within-tier story is the part that has actionable answers — if anyone in city government is asking the right question.
Notes, Sources, and Methodology
All data is the OpenDataPhilly 311 Service Requests table public_cases_fc, pulled on 2026-06-08. The window is 2024-01-01 through 2026-06-08, restricted to closed rows with an actual_days in [0, 365] days. Zips with fewer than 1,000 closed tickets in the window are excluded from the rankings and the OLS regression.
The income-vs-wait relationship is fit with a single-variable OLS regression on 43 zips: median_days = 10.8 + (−6.6 × 10−5) × median_household_income. R² is 0.19 — income alone explains 19% of the variance in median wait time. A residual is the gap between a zip’s actual median wait and the line’s prediction; positive means slower than income alone explains, negative means faster.
The chronic-pair rate counts (rounded address, service-name) pairs with at least 5 reports spanning at least 365 days, normalized per 1,000 closed tickets. Income figures are ACS five-year estimates, which can lag rapid neighborhood change — see the Norris Square caveat in the bright-spots section above.