data/analysis/philly-enrollment-capacity.json
Served verbatim from the project repository. Internal working document conventions apply: documents may reference file paths, branch names, and findings-ledger anchors from the repo.
{
"meta": {
"generated_at": "2026-09-22T04:51:57.937274Z",
"generated_at_note": "The extract's retrieval timestamp from provenance.json, not the time this script ran — the packet is a pure function of the committed CSVs, the snapshot's provenance.json and the committed NYC and Miami-Dade packets, so it reproduces byte-for-byte.",
"source": {
"source_id": "sdp_facilities_dashboard",
"publisher": "School District of Philadelphia, Office of Operations",
"url": "https://www.philasd.org/fpp/",
"format": "qlik-engine-api",
"qlik_app_id": "2d47abaf-02e1-4671-adba-ea661203eda5",
"snapshot": "2026-09-22",
"sha256": "18b9791617edada6d3ec991595941284749afaa9c0e2a4264c9a2a9fbba51191",
"extract": [
"data/cities/philly/reference/parsed/sdp_facilities_sites.csv",
"data/cities/philly/reference/parsed/sdp_facilities_buildings.csv"
],
"rows_sites": 428,
"rows_buildings": 502
},
"vintage": "2024-25",
"single_vintage": true,
"single_vintage_reason": "The School District of Philadelphia (SDP) publishes one facilities vintage, SY2024-25. The app's School Year field is a cross-join onto the student table, so a site's capacity appears under both labels with identical figures (335 of the 342 (ULCS, site) pairs carrying a capacity appear under both labels; 0 differ) — no trend and no enrollment-vs-capacity decomposition of the NYC kind is possible from this source.",
"grain": "distinct site (site_id), deduplicated across program rows, District sector only",
"utilization_definition": "Site Utilization = (Site Enrollment + Site Pre-K Allotment) / Site Capacity, October 1 enrollment snapshot, SY2024-25",
"prek_note": "The dashboard adds the Pre-K seats allotted to a site's early-childhood programmes to its K-12 October 1 enrollment ('students enrolled (and allotted seats for PreK)'). NYC's Blue Book enrollment and Miami-Dade's October (FLDOE Survey 2) headcount, PK-12, count enrolled Pre-K children instead (NYC also 3-K), and NYC's target capacity includes Pre-K rooms, so the three are not on one Pre-K basis.",
"quantile_method": "exclusive (Weibull / R type-6), the default of Python's statistics.quantiles used by docs/cities/philly/probe/facilities.py. p10/p25/p75/p90 are rounded to integers and the median to one decimal, as published in doc §4.1.",
"direction": "NEUTRAL — utilization is reported, not ranked. Nothing here scores a school.",
"universe_note": "The universe narrows in two steps: 428 site rows resolve to 328 distinct sites, because a site hosting several programs publishes one set of capacity and enrollment figures across several rows; 215 of those 328 sites are District-sector sites carrying both a capacity and an enrollment, and those 215 are the universe of every figure here. The 113 distinct sites not carried forward are Charter, Alternative or Pre-K sector, or carry no capacity or no enrollment. The 342 in the note that SDP publishes one facilities vintage is a different count at a different grain — distinct (ULCS code, site) pairs carrying a capacity anywhere in the app, across every sector and both School Year labels (doc §2) — and is quoted there only to show that the two labels carry identical capacity figures. Charter coverage in this extract is thin, so any district-wide figure is a district-sites figure.",
"cross_city_note": "All three on SY2024-25. Philadelphia: median 67.1%, 24.7% under 50%, 7.9% under a third, 68.4% overall (215 district sites). Miami-Dade: median 66.7%, 21.2%, 4.7%, 69.7% (316 district-run regular schools). NYC: median 80%, 13.3%, 3.6%, 83.1% (1,702 schools in DOE buildings). The denominators differ — SDP site capacity, permanent FISH (Florida Inventory of School Houses) capacity, SCA (NYC School Construction Authority) target capacity — and so do the universes and the Pre-K basis: Philadelphia adds allotted Pre-K seats to K-12 enrollment, Miami-Dade and NYC count enrolled Pre-K children (NYC also 3-K), and NYC's target capacity includes Pre-K rooms. SDP assigns site capacity to Pre-K space as well: its five Pre-K-only sites carry site capacities of 60 to 221. Whether Miami-Dade's FISH capacity counts Pre-K stations is not established. Name the numerator, the denominator and the year whenever the three appear together.",
"checks": {
"published_vs_recomputed_utilization": {
"n": 215,
"max_abs_difference_pp": 4.77e-12,
"note": "The published Site Utilization equals (K-12 enrollment + allotted Pre-K seats) ÷ site capacity to floating-point tolerance, confirming the allotment sits inside the numerator (doc §6.1)."
},
"share_under_33_threshold": {
"note": "The under-33% share counts sites strictly under 33%. The method doc's measurement script uses < 33.3; no site falls between the two, so both give the same count."
}
}
},
"distribution": {
"district_sites": {
"n": 215,
"p10": 37,
"p25": 51,
"median": 67.1,
"p75": 85,
"p90": 106,
"share_under_50": 24.7,
"share_under_33": 7.9,
"share_over_100": 13.5,
"sum_over_sum": 68.4
},
"by_school_level": [
{
"school_level": "Elementary-Middle",
"n": 106,
"p10": 38,
"p25": 49,
"median": 65.5,
"p75": 85,
"p90": 100,
"share_under_50": 27.4,
"share_under_33": 7.5,
"share_over_100": 9.4,
"sum_over_sum": 68.2
},
{
"school_level": "Elementary",
"n": 46,
"p10": 52,
"p25": 57,
"median": 72.2,
"p75": 94,
"p90": 112,
"share_under_50": 6.5,
"share_under_33": 2.2,
"share_over_100": 21.7,
"sum_over_sum": 78
},
{
"school_level": "High",
"n": 46,
"p10": 36,
"p25": 49,
"median": 64.8,
"p75": 84,
"p90": 111,
"share_under_50": 28.3,
"share_under_33": 8.7,
"share_over_100": 10.9,
"sum_over_sum": 65.9
},
{
"school_level": "Middle",
"n": 12,
"p10": 20,
"p25": 25,
"median": 45.8,
"p75": 75,
"p90": 102,
"share_under_50": 50,
"share_under_33": 33.3,
"share_over_100": 16.7,
"sum_over_sum": 57.1
},
{
"school_level": "Middle-High",
"n": 4,
"p10": 33,
"p25": 39,
"median": 77.7,
"p75": 116,
"p90": 120,
"share_under_50": 25,
"share_under_33": 0,
"share_over_100": 50,
"sum_over_sum": 71.5
},
{
"school_level": "Elementary-Middle-High",
"n": 1,
"p10": 49,
"p25": 49,
"median": 48.8,
"p75": 49,
"p90": 49,
"share_under_50": 100,
"share_under_33": 0,
"share_over_100": 0,
"sum_over_sum": 48.8
}
],
"split_campus_sensitivity": {
"schools": [
{
"ulcs_code": "2210",
"sites": [
"S016",
"S148"
]
},
{
"ulcs_code": "7440",
"sites": [
"S234",
"S278"
]
},
{
"ulcs_code": "8770",
"sites": [
"S100",
"S130"
]
}
],
"students_counted_more_than_once": 1871,
"merged": {
"n": 212,
"p10": 37,
"p25": 50,
"median": 66.6,
"p75": 83,
"p90": 102,
"share_under_50": 25,
"share_under_33": 8,
"share_over_100": 11.8,
"sum_over_sum": 67.4
},
"merged_lift": {
"cut": 66,
"flagged_n": 105,
"flagged_close_n": 14,
"flagged_close_rate": 13.3,
"rest_n": 107,
"rest_close_n": 2,
"rest_close_rate": 1.9,
"lift": 7.13,
"p_value": 0.0015
},
"note": "Three district schools have classroom capacity on more than one site of their own: 2210 (S016, S148), 7440 (S234, S278), 8770 (S100, S130). The dashboard repeats a school's whole enrollment on each of its sites, so each of those six published site figures divides the whole school by one site's capacity, and the distribution above, which keeps SDP's published per-site basis, counts 1,871 students more than once. Merged into one unit per school — enrollment once, Pre-K seats and capacity summed — the 212 units read a median of 66.6%, 25.0% under 50%, 8.0% under 33%, 11.8% over 100% and 67.4% overall, against 67.1%, 24.7%, 7.9%, 13.5% and 68.4% on the 215 sites as published. The Close lift under 66% reads 7.13x on 105 units (p = 0.0015) against 7.47x on 104 sites. None of the six sites carries a Close recommendation (Modernize), so no Close count changes."
}
},
"co_location": {
"n_sites": 215,
"sites_hosting_more_than_one_program": 80,
"share": 37.2,
"max_programs_on_one_site": 3,
"note": "A site hosting a district school plus its Pre-K program, or plus a co-located charter, publishes one set of capacity/enrollment figures across several program rows. The distribution above counts each site once."
},
"decision_lift": {
"universe": "distinct district sites carrying a capacity, an enrollment and a published Program Change",
"n": 215,
"close_n": 16,
"base_rate": 7.4,
"close_definition": "Program Change beginning with \"Close\" — the district's own vocabulary: Close, Close + Repurpose, Close, Modernize, + Repurpose.",
"cuts": [
{
"cut": 33,
"flagged_n": 17,
"flagged_close_n": 5,
"flagged_close_rate": 29.4,
"rest_n": 198,
"rest_close_n": 11,
"rest_close_rate": 5.6,
"lift": 5.29,
"p_value": 0.0043
},
{
"cut": 50,
"flagged_n": 53,
"flagged_close_n": 10,
"flagged_close_rate": 18.9,
"rest_n": 162,
"rest_close_n": 6,
"rest_close_rate": 3.7,
"lift": 5.09,
"p_value": 0.00093
},
{
"cut": 66,
"flagged_n": 104,
"flagged_close_n": 14,
"flagged_close_rate": 13.5,
"rest_n": 111,
"rest_close_n": 2,
"rest_close_rate": 1.8,
"lift": 7.47,
"p_value": 0.0012
},
{
"cut": 75,
"flagged_n": 140,
"flagged_close_n": 15,
"flagged_close_rate": 10.7,
"rest_n": 75,
"rest_close_n": 1,
"rest_close_rate": 1.3,
"lift": 8.04,
"p_value": 0.013
}
],
"size": {
"predictor": "enrollment including allotted Pre-K seats (the utilization numerator) under 300",
"flagged_n": 47,
"flagged_close_n": 12,
"flagged_close_rate": 25.5,
"rest_n": 168,
"rest_close_n": 4,
"rest_close_rate": 2.4,
"lift": 10.72,
"p_value": 0.0000032
},
"ablation": [
{
"stratum": "enrollment including allotted Pre-K seats under 400",
"n": 91,
"close_n": 13,
"cut": 50,
"flagged_n": 38,
"flagged_close_n": 9,
"flagged_close_rate": 23.7,
"rest_n": 53,
"rest_close_n": 4,
"rest_close_rate": 7.5,
"lift": 3.14,
"p_value": 0.037
},
{
"stratum": "enrollment including allotted Pre-K seats of 400 or more",
"n": 124,
"close_n": 3,
"cut": 66,
"flagged_n": 38,
"flagged_close_n": 3,
"flagged_close_rate": 7.9,
"rest_n": 86,
"rest_close_n": 0,
"rest_close_rate": 0,
"lift": null,
"p_value": 0.027
}
],
"p_value_note": "Fisher two-sided p-values are carried from docs/cities/philly/06_enrollment_capacity_utilization.md §4.3 (and §4.1 for the split-campus sensitivity), where they were measured with scipy.stats.fisher_exact. They are not recomputed here. The counts behind the utilization-cut p-values are in Table 2. For the size comparison, the comparisons within enrollment including allotted Pre-K seats under 400 and 400 or more, and the split-campus sensitivity, the script that builds these figures stops if the counts move from the ones the p-values were measured on. A null lift means no site on the other side of the cut carries a Close recommendation, so the ratio is unbounded.",
"interpretation": "Both the predictor and the reference come from the same publication, so this measures how closely the district's recommendation tracks its own stated criterion, not whether an outside observer could have predicted the list. Size is the stronger single predictor: on the same 215 sites, enrollment including allotted Pre-K seats under 300 carries a 10.72x lift (25.5% of 47 sites against 2.4% of 168, p < 0.0001; doc §4.3)."
},
"denominator_sensitivity": {
"n_matched_sites": 207,
"site_capacity": {
"basis": "Site Capacity — the figure the district publishes and plans on",
"median_utilization": 67.1,
"share_under_50": 25.1,
"n_under_50": 52,
"sum_over_sum": 67.6
},
"summed_building_capacity": {
"basis": "BLDGCAPACITY summed over the distinct buildings on the site (the dashboard's \"Current Capacity (OLD)\")",
"median_utilization": 61.8,
"share_under_50": 31.4,
"n_under_50": 65,
"sum_over_sum": 69.5
},
"under_50_swing_pp": 6.3,
"ratio_building_over_site": {
"p10": 0.754,
"p25": 0.85,
"median": 0.989,
"p75": 1.137,
"p90": 1.301,
"share_over_1_2": 16.9,
"share_under_0_9": 32.9
},
"ratio_by_school_level": [
{
"school_level": "Elementary-Middle",
"n": 102,
"median_ratio": 0.966
},
{
"school_level": "High",
"n": 45,
"median_ratio": 0.955
},
{
"school_level": "Elementary",
"n": 44,
"median_ratio": 1.078
},
{
"school_level": "Middle",
"n": 11,
"median_ratio": 0.962
},
{
"school_level": "Middle-High",
"n": 4,
"median_ratio": 0.953
},
{
"school_level": "Elementary-Middle-High",
"n": 1,
"median_ratio": 1.666
}
],
"full_universe_site_capacity_reference": {
"n": 215,
"median_utilization": 67.1,
"share_under_50": 24.7,
"note": "The two bases are compared on the 207 sites carrying both. The headline distribution covers 215 sites, 8 of which carry no BLDGCAPACITY; on that wider set the site-capacity basis reads 67.1% median and 24.7% under 50%."
},
"building_extract": {
"rows": 502,
"distinct_buildings": 399,
"repeated_buildings": 94,
"max_rows_per_building": 4,
"buildings_on_a_site": 362,
"buildings_with_no_site": 37,
"sites_with_a_building": 285,
"sites_with_more_than_one_building": 47,
"sites_with_building_capacity": 236,
"sites_a_row_sum_inflates": 79,
"note": "The extract carries one row per (building, programme): a building on a site hosting several programmes repeats, identical on every column but ulcs_code. Summing rows would count such a building once per programme. Every figure above counts each building once; sites_a_row_sum_inflates is the number of sites whose sum a row sum would change."
},
"nyc_reference": {
"year": "2013-14",
"n": 1747,
"share_under_50_target": 6.4,
"share_under_50_historical": 8.8,
"swing_pp": 2.4,
"source": "data/analysis/nyc-enrollment-capacity.json → capacity_definitions"
},
"note": "On the 207 district sites carrying both figures, BLDGCAPACITY summed over each site's distinct buildings reads a median 61.8% and 31.4% of sites under 50% (65), against 67.1% and 25.1% (52) on Site Capacity: the choice of denominator moves the under-50% share by 6.3 points. In aggregate the two bases are close — enrollment over summed capacity is 69.5% on the building basis and 67.6% on the site basis — but site by site they are not: building over site capacity runs from 0.754 at p10 to 1.301 at p90. The dashboard names BLDGCAPACITY \"Current Capacity (OLD)\", labels its OLD figures 2017, and divides a SY2016-17 enrollment count by it; SDP documents nothing more about how either capacity figure was measured. Dividing 2024-25 enrollment by it, as here, is a pairing the dashboard never makes, so part of the site-by-site difference may be capacity that changed after 2017 rather than a difference of definition. Treat it as an alternative denominator that shows the sensitivity, not a rival estimate. NYC's two-formula ambiguity (target vs historical capacity), measured within one year (2013-14, 1,747 schools), moves its under-50% share by 2.4 points. That is a comparison of sensitivities, not of levels: the two cities count Pre-K on different bases (Philadelphia adds allotted seats; NYC counts enrolled Pre-K children against a target capacity that includes Pre-K rooms), and the two are readings of different school years (Philadelphia 2024-25, NYC 2013-14)."
},
"recommendation_mix": [
{
"program_change": "Modernize",
"n": 137,
"share": 63.7,
"is_close": false
},
{
"program_change": "Maintain",
"n": 50,
"share": 23.3,
"is_close": false
},
{
"program_change": "Close",
"n": 7,
"share": 3.3,
"is_close": true
},
{
"program_change": "Close, Modernize, + Repurpose",
"n": 7,
"share": 3.3,
"is_close": true
},
{
"program_change": "Modernize + Co-Locate",
"n": 4,
"share": 1.9,
"is_close": false
},
{
"program_change": "Co-Locate",
"n": 3,
"share": 1.4,
"is_close": false
},
{
"program_change": "Co-Locate + Modernize",
"n": 3,
"share": 1.4,
"is_close": false
},
{
"program_change": "Close + Repurpose",
"n": 2,
"share": 0.9,
"is_close": true
},
{
"program_change": "Maintain (future relocation)",
"n": 1,
"share": 0.5,
"is_close": false
},
{
"program_change": "Relocate + Modernize",
"n": 1,
"share": 0.5,
"is_close": false
}
],
"cross_city": {
"year": "2024-25",
"rows": [
{
"city": "Philadelphia",
"grain": "site",
"universe": "Distinct District-sector sites carrying a capacity and an enrollment",
"n": 215,
"median": 67.1,
"share_under_50": 24.7,
"share_under_33": 7.9,
"share_over_100": 13.5,
"sum_over_sum": 68.4,
"cuts": {
"under_33": "<33",
"over_100": ">100"
},
"numerator": "K-12 October 1 enrollment plus the Pre-K seats allotted to the site",
"denominator": "SDP site capacity",
"source": "data/analysis/philly-enrollment-capacity.json → distribution.district_sites"
},
{
"city": "Miami-Dade",
"grain": "school",
"universe": "District-run regular schools (K-12 general education, not charter) carrying an October headcount and a permanent FISH capacity, K-8, 6-12 and K-12 schools included",
"n": 316,
"median": 66.7,
"share_under_50": 21.2,
"share_under_33": 4.7,
"share_over_100": 7.9,
"sum_over_sum": 69.7,
"cuts": {
"under_33": "<33.33",
"over_100": ">=100"
},
"numerator": "FLDOE Survey 2 (October) headcount, PK-12: enrolled Pre-K children included",
"denominator": "Permanent FISH capacity",
"source": "data/analysis/miami-enrollment.json → utilization"
},
{
"city": "NYC",
"grain": "school",
"universe": "Schools whose org code resolves to exactly one DBN, in DOE buildings, co-located charters (about 110) and District 75 (about 60) included",
"n": 1702,
"median": 80,
"share_under_50": 13.3,
"share_under_33": 3.6,
"share_over_100": 26.2,
"sum_over_sum": 83.1,
"cuts": {
"under_33": "<33.3 (integer percents)",
"over_100": ">100"
},
"numerator": "Blue Book enrollment, the audited register: enrolled 3-K and Pre-K children included",
"denominator": "SCA target capacity, Pre-K rooms included",
"source": "data/analysis/nyc-enrollment-capacity.json → by_year[\"2024-25\"].school"
}
]
}
}