Where shots land
17,623 shootings since 2015, plotted block by block, then rolled up by police district. The pandemic-era surge, the partial recovery, and the small handful of districts carrying the load.
Philadelphia is policed by 21 districts in this dataset. Each shooting in the shootings table carries a dist field naming the district that
responded; the polygons come from the matching police_districts table.
Hold the geography in your head. Next, watch three years land on top of it: 2019 baseline, 2021 peak, 2024 partial recovery. The dot cloud goes brick at the peak.
The arc is three frames. 2019 — the last full year before the pandemic — ran 1,472 shootings, already concentrated in the same clusters that show up in Where Philly burns and The Narcan map. 2021 spiked to 2,341 — the highest single-year total in the dataset, roughly 1.6× the 2019 count. 2024 settled at 1,108 — lower than the peak, higher than the baseline. The map holds on 2021 because the peak frame carries the shape; the next beat fills in every intervening year.
Three frames isn't the shape — the shape is the run. The map now cycles through every year in the dataset from 2015 to 2026, a frame every 1.5 seconds. Watch the cloud breathe outward through 2020 and 2021, then contract — unevenly — through the recovery.
Frame: 2015 · 1,286 shootings
Roll up to the district level: the polygons recolor by all-time totals
from SHOOTING_VIEWS.countByDistrict().
The top-3 districts — saturated brick on the map — sit at the
head of the ranking shown in the bars below
(D25, D22, D24).
The remaining 18 districts are dimmed; the rest of
the ranking sits in the bar chart.
Now switch the question. Instead of "where did the most shootings happen", ask "where were the most fatal." The bars below reshuffle in place: districts slide left or right to their new rank while their heights morph. The map's top-3 also recolors — (D25, D22, D24). Some overlap with the raw-count top-3; some don't. Lethality isn't a property of volume alone.
Same 21 districts, recolored by how much the peak year (2021) differed from 2019. Districts that grew are brick; districts that fell — none, in the end — would read fern. The darkest bricks aren't always the same districts that top the raw-count ranking: a district can be a top-3 hotspot in 2019 and still grow modestly into 2021, while a quieter district that doubles tells a different story about where the surge actually landed.
View underlying data
Top-10 districts by all-time shootings, alongside fatal-shooting rank and peak-year % change vs 2019.
| District | All-time shootings | Fatal (all-time) | Peak Δ vs 2019 |
|---|---|---|---|
| D25 | 2,117 | 424 | — |
| D22 | 2,007 | 413 | — |
| D24 | 1,723 | 361 | — |
| D35 | 1,387 | 277 | — |
| D39 | 1,324 | 281 | — |
| D15 | 1,292 | 270 | — |
| D12 | 1,275 | 294 | — |
| D19 | 1,233 | 249 | — |
| D14 | 926 | 212 | — |
| D18 | 853 | — | — |
Data Sources
Primary datasets: shooting-victims (one row per victim) and police-districts (21 polygons), both via phl.carto.com. Frozen at deploy (2026-05-13).
Queries: SHOOTING_VIEWS.countByYear() for the yearly sparkline and 2019 baseline, SHOOTING_VIEWS.pointsForYear(year) for each of the three focus-year point
clouds (2019, 2021, 2024), SHOOTING_VIEWS.countByDistrict() for the
all-time district shading, SHOOTING_VIEWS.fatalShareByDistrict() for the
fatality view, and SHOOTING_VIEWS.districtPolygons() for the polygon
geometry. All defined in src/lib/data/datasets/philly-shootings.ts.
Methodology & caveats: One row per victim — multi-victim incidents
appear as multiple rows. The peak-vs-baseline ratio in the 2021 beat divides data.totals.peakCount by data.totals.preCovidBaseline (the
2019 row from the same yearly query); we deliberately don't hardcode either number.
Per-incident outcome and clearance data isn't published — see data we'd like to find.