← Back to story

Year-over-year moversMethodology recipe

Five years later, where did the Renewal Schools land?

A reproducibility log: the data this analysis touched, the queries it ran, the outside sources it leaned on, and the steps a third party would follow to re-run it.

Summary

Joined the canonical 94-school 2014 Renewal Schools roster (from Chalkbeat's launch-day list) to our schools table with JS-side fuzzy matching (token Jaccard ≥ 0.5 on normalized names), then pulled per-school outcome trajectories for the 85/94 matches and compared with citywide and same-decile non-Renewal peers.

Data sources

  • Database tableschools

    One row per New York City public school (DBN, name, district, borough, school_type, grade_band, latest_enrollment, proclivity_decile, proclivity_score, closed_at, admission_category).

  • Database tableschool_year_metrics

    Long-format per-school per-year metric facts (school_dbn, year, metric_key, subgroup, value, suppressed). Loaded from DOE/NYSED public files via scripts/loaders/*.

  • Database tableproclivity_score / proclivity_decile

    Composite student-body-challenge score (lower = lower-need, higher = higher-need) built from % economically disadvantaged, % English Language Learners, % students with disabilities. Decile 1 = lowest-need; decile 10 = highest-need.

  • Loader scriptscripts/loaders/_renewal_query.ts

    Holds the verbatim 94-school roster, the JS-side fuzzy-matcher, and all comparison queries. Run with `npx tsx scripts/loaders/_renewal_query.ts > data/stories/renewal-data.json`.

  • Cached outputdata/stories/renewal-data.json

    Cached output: 85 matches, per-school trajectories, peer comparison, summary stats.

  • External datasetChalkbeat: "These 94 schools are set to receive extra funding and learning time" (2014-11-03)

    Authoritative launch-day roster of all 94 Renewal Schools.

Steps

  1. Pull all schools, then for each Renewal name compute a token Jaccard similarity (after lowercasing, expanding P.S./I.S./M.S./J.H.S., stripping leading zeros, dropping stopwords like 'school'/'academy'/'the'). Accept the highest score above 0.5.

    function tokens(s) { /* normalize then split */ }
    function jaccard(a, b) { /* |A∩B| / |A∪B| */ }
    // Apply to every Renewal name × every row in the schools table; take argmax with score ≥ 0.5.
  2. Per-school chronic-absenteeism and ELA/math proficiency trajectory, comparing 2018-19 and 2024-25 for the 61 still-open matched Renewal schools.

    SELECT s.dbn, s.name,
           MAX(CASE WHEN m.year='2018-19' THEN m.value END) AS y2018,
           MAX(CASE WHEN m.year='2024-25' THEN m.value END) AS y2024
      FROM schools s
      JOIN school_year_metrics m ON m.school_dbn = s.dbn
     WHERE s.dbn = ANY($1::text[])
       AND m.metric_key IN ('chronic_absenteeism_rate','ela_all_proficiency','math_all_proficiency')
       AND m.subgroup='ALL' AND m.suppressed=false
     GROUP BY s.dbn, s.name;
  3. Peer comparison: for each proclivity decile, average 2024-25 chronic absenteeism for non-Renewal schools, then compare with the matched-Renewal medians for that decile.

    SELECT s.proclivity_decile, AVG(m.value), COUNT(*)
      FROM schools s
      JOIN school_year_metrics m ON m.school_dbn = s.dbn
     WHERE s.dbn NOT IN (<renewal DBNs>)
       AND m.metric_key='chronic_absenteeism_rate'
       AND m.subgroup='ALL' AND m.year='2024-25' AND m.suppressed=false
     GROUP BY s.proclivity_decile;
  4. Citywide ELA/math proficiency trend for the same years, so reported Renewal Δs can be put in citywide context.

Caveats

85/94 schools matched in our data; 9 likely closed before our metric coverage began. The 1900-01-01 sentinel date marks 'closed but year-of-closure unknown.' Test-proficiency comparisons span the 2022-23 state-test recalibration, which raised proficiency rates citywide — we report absolute changes against the citywide median so both lines absorb the recalibration. Our graduation-rate field doesn't cover 2014-15, so we can't directly test whether RAND's mid-program graduation-rate gains persisted.

References

Reproduce

Run `npx tsx scripts/loaders/_renewal_query.ts > data/stories/renewal-data.json` against a database with the project schema loaded. The script bundles the 94-school roster (copy-pasted from Chalkbeat 2014-11-03) and re-derives every figure in the story. To audit the fuzzy match, dump the `matches` array — each entry shows the Jaccard score so false positives are visible.

The recipe lives at data/stories/recipes.ts in the repo. Corrections welcome.