| Within (miles) | Status quo | Scenarios A and B |
|---|---|---|
| Whole tract at one point | ||
| 0.5 | 12% | 10% |
| 1.0 | 59% | 35% |
| 1.5 | 65% | 45% |
| 2.0 | 84% | 69% |
| Spread over blocks (used) | ||
| 0.5 | 24% | 10% |
| 1.0 | 52% | 36% |
| 1.5 | 68% | 51% |
| 2.0 | 76% | 60% |
| School-age (5-17) Spanish speakers living within each distance of a K-5 Spanish immersion site. | ||
Sources & methods
Where every number comes from, how it was processed, and what it can’t tell you
Credits: this site builds on pps-explorer
This site builds on pps-explorer by Jason Brown (@browniefed), an interactive map of the PPS boundary scenarios. Every scenario comparison on this site rests on two parts of pps-explorer:
- its attendance areas and school locations, which it digitized from the PPS scenario map PDFs and georeferenced (placed on real map coordinates)
- its transcription of the October 2026 board memo (closures, program moves and grade changes).
pps-explorer in turn credits ppsdata.info by Alex Meub (meub/pps-data).
This is an independent analysis, not a PPS publication. If anything here differs from PPS documents, the PPS documents are authoritative.
All of the code, the saved source documents and the cleaned tables are on GitHub at github.com/jminnier/pps-dli-explorer. You are welcome to post corrections and questions there as issues.
Where the data come from
We saved every source document in the repository under data-raw/. The script listed for each source turns it into a table in data/. When a row fails its checks, the script stops with an error instead of guessing.
| # | Data | Publisher and document | Years | Saved source files | Script → table |
|---|---|---|---|---|---|
| 1 | Immersion enrollment by school and language | PPS Data & Reporting, Enrollment Details for Language Immersion Schools (“Language Immersion Track Profiles”): 2024-25 and 2025-26 on the Data & Reporting page, earlier years on the archive page | October 2021 to October 2025 | data-raw/pps_reports/*_Language_Immersion_Track_Profiles.pdf |
parse_immersion_profiles.py → dli_track_profiles.csv |
| 2 | Enrollment by school, program and grade | PPS Data & Reporting, Enrollment by Grade and Program Type | October 2024, October 2025 | data-raw/pps_reports/*_Enrollment_by_Grade_and_Program_Type.pdf |
parse_program_type.py → enrollment_by_program_grade.csv |
| 3 | Enrollment by school, program and home language | PPS Data & Reporting, Enrollment by Language and School | October 2024, October 2025 | data-raw/pps_reports/*_Enrollment_by_Language_and_School_Map.pdf |
parse_language_by_school.py → enrollment_by_language.csv |
| 4 | Lottery applications, offers, waitlists | PPS Enrollment & Transfer, Elementary School Lottery Results Summary, Kindergarten Lottery Results Summary and Middle & High School Lottery reports, on the prior lottery results page | Lotteries for 2021-22 to 2026-27 | data-raw/pps_lottery/*.pdf (13 files) |
parse_lottery.py → lottery_results.csv |
| 5 | Enrollment forecasts | Portland State University Population Research Center, Portland Public Schools Enrollment Forecasts, Tables 5.2–5.5 | 2025-26 and 2026-27 editions | data-raw/pps_reports/PSU_PRC_Forecast_*.pdf |
parse_psu_forecast.py → psu_forecast.csv |
| 6 | Average kindergarten class size | PPS, Class Size Detail (archive page and Data & Reporting page) | 2018-19 to 2025-26 | data-raw/pps_reports/class_size/*.pdf |
copied by hand for Lent and Bridger → class_size_kg.csv |
| 7 | District enrollment by grade (K–5), October 2022 | PPS, Enrollment – Summary Comparison (October 3, 2022), in School Enrollment Profiles & Demographics on the archive page | 2022-23 | – | the six grade totals, entered directly in scorecard.qmd |
| 8 | Immersion sites and program moves in each scenario | PPS board packet for October 6, 2026: Status Quo, Scenario A and Scenario B attendance-area map PDFs, and the Rightsizing Update: Scenario Release memo (October 5, 2026) with the regional summaries; digitized and transcribed in pps-explorer | Scenarios released October 2026 | public/data/*.geojson, src/lib/changes-data.mjs |
export_dli_tables.mjs → dli_sites.csv, dli_moves.csv |
| 11 | PPS subgroup move rates and scenario memo | PPS Board of Education, 10/06/26 PowerPoint (slide 44, “Balance and Impact: Kindergarten – 8th Grade Students Who Move”; slide 13) and Rightsizing Update: Scenario Release memo (October 5, 2026), via BoardBook; also compiled by Save PDX Schools | October 2026 | data-raw/pps_board/, data-raw/savepdxschools/ |
slide 44 table copied to pps_slide44.csv (checked against the PDF text) |
| 12 | School demographics | PPS, School/Neighborhood Enrollment by Ethnicity & Program (School and Neighborhood rows: race/ethnicity, direct certification, English learners, TAG, language immersion, focus/alternative, historically underserved) | October 2024, October 2025 | data-raw/pps_board/school_neighborhood_enroll_ethnicity_program_*.pdf |
parse_ethnicity_program.py → school_demographics.csv |
| 13 | Evaluation of the 2023 Southeast changes | Green, T. L., & Hanson, H. (2026, June 10). Equity audit evaluation of Portland Public Schools’ Southeast Enrollment and Program Balancing | 2020-21 to 2025-26 | data-raw/pps_transcripts/SEGC_Equity_Audit_Evaluation_Report.pdf |
quoted with page numbers |
| 14 | Board meeting statements | Automated transcripts of PPS board and committee meetings compiled by Save PDX Schools, checked against the meeting video | Sept–Oct 2026 | data-raw/pps_transcripts/*.json |
quoted with meeting, date and time |
| 15 | Older enrollment forecasts | PSU Population Research Center, Portland Public Schools Enrollment Forecasts, 2022-23 (June 2022), 2023-24 (June 2023) and 2024-25 (July 2024) editions, Appendix C / Table 5.5 | 2019-20 to 2033-34 | data-raw/pps_reports/PSU_PRC_Forecast_*_edition.pdf |
extract_psu_premove.py → psu_forecast_premove.csv |
| 16 | Scenario projections by school | PPS, How Could Your School Be Impacted? (page): one 4-page “Family-Friendly School Guide” per school (82 PDFs, served from Google Drive through an Awesome Table list; metadata title “Confidential Draft”, all dated October 8, 2026) | Projections 2027-28 to 2031-32 | data-raw/pps_board/impact_page/*.pdf, drive_ids.txt |
parse_school_guides.py → guide_enrollment.csv, guide_school.csv, guide_text.csv |
| 17 | Audit school-by-school appendix | Green, T. L., & Hanson, H. (2026, June 29). Equity audit evaluation of Portland Public Schools’ Southeast Enrollment and Program Balancing initiative: School-by-school analysis, from the PPS SEGC documents page | 2020-21 to 2025-26 | data-raw/pps_transcripts/SEGC_Equity_Audit_School_by_School_Analysis.pdf |
quoted with page numbers |
| 18 | Neighborhood capture rates | PPS, Neighborhood Capture Rate Metrics (“Enrollment Summary … by K-12 Students’ Neighborhood and Type of School Attended”); 2024-25 and 2025-26 on the Data & Reporting page, earlier years on the archive page under “Neighborhood Attendance Patterns & Focus Distributions”. The companion School Enrollment by Neighborhood of Residence reports are source 19 | October 2019 to October 2025 | data-raw/pps_reports/capture_rate/*.pdf |
parse_capture_rate.py → capture_rate.csv |
| 19 | Where each program’s students live | PPS, School Enrollment by Neighborhood of Residence (Data & Reporting page; earlier years on the archive page) | October 2023 to October 2025 parsed (2019-20 to 2022-23 saved; rotated pages not yet parsed) | data-raw/pps_reports/capture_rate/*_Enroll_by_Neighborhood.pdf |
parse_enroll_by_neighborhood.py → enroll_by_neighborhood.csv |
| 20 | International School of Portland (private) | NCES Private School Universe Survey, 2023-24 (total 376, grades PK-5); kindergarten count (72) from the US News profile, whose grade counts sum to the NCES total; language tracks from the school’s website | 2023-24 | – | quoted on the equity page |
| 21 | Building capacity | PPS, Long-Range Facility Plan 2021, Volume 1, Enrollment & Utilization tables (p. 53 elementary, p. 57 K-8, p. 60 middle); also compiled in meub/pps-data (MIT license) | 2021 | data-raw/pps_reports/facility/LRFP_Vol1_2021.pdf |
parse_lrfp_capacity.py → facility_capacity_2021.csv |
| 22 | Current building capacity and school profile | PPS, School Profiles Power BI dashboard on the internal school profiles page: functional capacity, 2025-26 utilization, enrollment, 2026-27 projection, direct certification, capture rate, program type, per school | 2025-26 (retrieved Oct 9, 2026) | data-raw/pps_reports/school_profiles/*.txt (text snapshot of each school’s view) |
scrape_school_profiles.mjs, parse_school_profiles.py → school_profiles_2025.csv |
| 23 | Race and ethnicity by program | PPS, Enrollment Summary by Race and Ethnicity, October 2025 (PDF): counts and percentages for eight groups, with separate rows for each school’s immersion and neighborhood programs | October 2025 (retrieved October 11, 2026) | data-raw/pps_reports/race/EnrollmentbyRace25-26.pdf |
parse_race_by_program.py → race_by_program_2025.csv; equity_race.R → equity_race_*.csv |
| 24 | History of PPS and Black Portlanders | PPS, Center for Black Student Excellence, Historical Context; City of Portland, Portland Housing Bureau, N/NE Neighborhood Housing Strategy: Historical Overview; PPS, Racial Educational Equity Policy (2.10.010-P) | retrieved October 11, 2026 | – | quoted on the Equity page (§3) |
| 25 | Title I schools | PPS Funded Programs, Title IA page: “2026-2027 Title IA Schools” (with bridge schools marked) and “2025-2026 Title IA Schools”, and the eligibility rule | 2025-26 and 2026-27 (retrieved October 11, 2026) | data-raw/title1/ |
title1_schools.csv (copied with school keys by school_changes.R) |
| 26 | SUN Community Schools | Multnomah County, SUN Community School Contact List – August 2026; proposed 2026 cuts from Willamette Week (June 2, 2026) and the county’s June 5, 2026 budget release | August 2026 (retrieved October 11, 2026) | data-raw/sun/ |
sun_schools.csv (via school_changes.R) |
| 27 | Special education staffing (requested by a board member) | Board Request as of 9/22 (Google Sheet), SPED tab, “2026-27 Projected Allocation”: Learning Center, SES, CB and ISC teacher positions and aides by school. Board member Virginia La Forte requested the data and shared the sheet on her Facebook account: “I wanted to see a basic lay of the land and requested this data: How many students and how many sections are there in every grade band at every school including blends? What does staffing look like? What does every individual middle school offer? How many students are in each of those classes? For the data-inclined, see link in comments.” It was also shared in the PPS Community Advocacy group. Not a published PPS report | Planned for 2026-27 (retrieved October 11, 2026) | data-raw/sped/ |
sped_allocation_2026_27.csv, sped_moves.csv (via sped_programs.R) |
| 28 | PPS committee slides on immersion and middle grades | PPS, PPS Dual Language Immersion (DLI) Programs and Middle School Student Experience: K-8 & 6-8 Schools, Teaching, Learning, and Enrollment Committee, October 13, 2026 | October 13, 2026 | data-raw/pps_board/tle_*_2026-10-13.pdf |
tle_dli_k_2026_27.csv, tle_k8_subsidy.csv (via tle_slides.R) |
| 29 | Freeways and school grounds | OpenStreetMap via the Overpass API: highway=motorway, highway=motorway_link and amenity=school polygons (ODbL) |
Snapshot of October 13, 2026 | data-raw/osm/ (cached response) |
freeway_distance.csv (via freeway_distance.R), freeway_*.csv (via freeway_equity.R) |
| 9 | Home language by census tract | US Census Bureau, American Community Survey 5-year estimates, tables C16001 (language spoken at home, population 5+) and B16007 (language spoken at home by age), via the Census API | 2020–2024 | cached locally, not committed | acs_language_access.R → acs_language_tract.csv, tracts.geojson, access_tract.csv, access_area.csv |
| 10 | Population by census block | US Census Bureau, 2020 Census redistricting data (P.L. 94-171), tables P1 and P3, via the Census API | 2020 | cached locally, not committed | used in acs_language_access.R and check_access_robustness.R → access_summary.csv, access_robustness.csv, access_robustness_ci.csv |
How we read and checked each source
1. Immersion enrollment by school (Language Immersion Track Profiles)
Each PDF lists every school that has an immersion program. Each school takes two lines: the counts, then the same counts as a percentage of the school’s total October enrollment. The columns are:
- total enrollment
- students who are multilingual learners (ML, students who are learning English) or in immersion
- students who are neither
- total immersion students
- immersion students by language (Spanish, Mandarin, Japanese, Russian, Vietnamese)
- total ML students
- ML students by primary language (Spanish, Chinese, Japanese, Russian, Vietnamese, Somali, Other)
- students who are both ML and in immersion
- a final percentage.
We handled five problems in these files:
- Reading the numbers. We extracted the text with
pypdf. In the 2021-22 and 2022-23 files, the PDF’s text layer (the machine-readable text behind the printed page) runs adjacent numbers together. For example, four zeros print as “0000”. So we split each school’s digits every possible way and kept the split where both of these are true:- every count matches its printed percentage of enrollment, within rounding (±0.51 points)
- the row identities hold: immersion total = sum of the five immersion languages; ML total = sum of the ML languages; “ML or immersion” = immersion + ML − both; “neither” = enrollment − “ML or immersion”.
- ML-language columns. In 2021-22 the text layer sometimes lists the ML-language counts out of column order. We matched them to columns by their printed percentages. In 21 school-years (2021-22 and 2022-23), the ML-language counts in the text layer don’t add up to the school’s own ML total. For those rows we left the ML-language breakdown blank and kept only the checked totals. No figure on this site uses the ML-language breakdown.
- Mislabelled column. The last column is headed “Percent of ML in Immersion (Both ML and Imm / ML)”. But the printed values are both ÷ total immersion (Ainsworth 2025: 38 ÷ 287 = 13%, whereas 38 ÷ 59 = 64%). We store it as
pct_immersion_ml. - Date typo. The 2023-24 file’s title reads “October 2022”. We treat it as 2023-24, which matches the PPS archive’s label and the file’s contents.
- Page breaks. Where a school’s percentage line falls on the next page (Richmond, 2025-26), we join it back to its count line.
2. Enrollment by grade and program type
This report lists each school by program (for example, “Spanish Immersion” or “Neighborhood Program”). Each row gives enrollment in each grade, PreK–12, and a total. A school with more than one program ends with a school total row. Schools are grouped into sections (elementary, middle, high, alternative, community-based, special services, charter). Each section has a total, and the report ends with a district total.
- We read cells by position. The text layer prints every grade cell, blank where a school doesn’t serve that grade. Counts over 999 contain commas, and we rejoined one program name that wrapped onto a second line.
- Checks (all pass for both years):
- each row’s grades sum to its total
- each school’s program rows sum to its school total in every grade
- schools sum to their section totals
- sections sum to the district total (44,086 in October 2024; 43,479 in October 2025).
- Whole-school immersion. Lent, Rigler and Richmond print as a single unlabelled row. Source 1 shows all of their students in immersion. So we tag them Spanish, Spanish and Japanese immersion respectively.
- Cross-check: immersion enrollment summed from this report equals the immersion totals in source 1 for every school in both years.
3. Enrollment by language and school
For each school and program, this report counts students by home-language group, as counts and percentages. The groups are English, Spanish, Vietnamese, Chinese, Russian, Somali/Maay-Maay, Japanese and Other. “Chinese” includes Cantonese, Mandarin and other Chinese languages (report footnote).
- The PDF text leaves out empty cells. So we assign each number to a column by its x-position (horizontal position) on the page, using column boundaries taken from the header row.
- Checks (all pass):
- language counts sum to the program’s enrollment
- every count matches its printed percentage (±0.51 points)
- program rows sum to the school total row
- all schools sum to the district total for every language.
- Cross-check: immersion enrollment by school and language equals source 1 exactly (64 school-years compared, 0 differences).
4. Lottery results
PPS publishes a results summary for each lottery. For each school and program, it gives the number of applications, offers, waitlisted applicants and cancelled applications. Some years also give the number of seats (“slots”) and of applicants not placed. “Cancelled” means the applicant was placed at a program they ranked higher. Waitlists are as of the spring lottery. Waitlisted applicants may still get an offer before the end of September.
The layout differs every year, so we handled each file separately:
| Lottery for | Layout notes | Columns available |
|---|---|---|
| 2021-22 | Plain text in order. Immersion rows have no grade printed; the MLK block is printed under the “Russian Immersion” heading but is Mandarin. | slots, applications, offered, waitlisted, cancelled, not placed |
| 2022-23 | Empty cells omitted; columns recovered from x-positions. Applicant groups and grades. | applications, offered, waitlisted, cancelled, not offered |
| 2023-24 | Complete cells; some split words rejoined. | slots, applications, offered, waitlisted, cancelled |
| 2024-25 | Page coordinates run top-down; rows attached to the nearest school heading above. | offered (“slots filled”), applications, waitlisted, cancelled |
| 2025-26 | Two-column pages; titles mixed into school-name lines. One non-immersion school (Buckman, grades 1–5) is printed with its columns out of order and was re-read so its rows add up. | as 2024-25 |
| 2026-27 (kindergarten) | Section headings and school names are printed at the end of each page’s text, so rows are read by position. Applicant groups by residence (NH, RG, TR) and language background (English, Heritage, Native). | offered, waitlisted, cancelled, applications |
- Language of each program comes from a list of schools and languages. We checked it against the immersion sites on the status-quo map (source 8) and source 1.
- Checks: Applicant-group rows sum to the printed school total in every year that prints totals (103 school totals in 2022-23, 2023-24 and 2026-27). The printed grand totals also match (7). The identity applications = offered + waitlisted + cancelled (+ not placed) holds in 846 of 848 testable rows. The two exceptions are printed that way in the source.
- Coverage. Every elementary immersion program appears in every year except Rigler, which appears in none. Middle and high school immersion appears in only one report, a small 2024-25 table without offers. So there is no lottery measure of demand for middle-grade programs.
5. PSU enrollment forecasts
We parsed Tables 5.2–5.4 (district by grade; medium, low and high scenarios) and 5.5 (by school and program, medium scenario only). We checked the printed subtotals and totals, allowing up to 3 students of rounding in forecast years. The base-year actuals match source 2 (435 comparisons). Richmond is printed with a total row only. We added a Japanese row equal to its total, as the report already does for Lent and Rigler. The forecast check on the Equity page and the Lent & César Chávez page use them.
6. Kindergarten class size
The Class Size Detail logs give each school’s average class size as of mid-October, overall and by grade group (kindergarten, grades 1–3, 4–5, …). We copied the kindergarten value for Lent and Bridger by hand from each year’s PDF into data/class_size_kg.csv, along with the name of the file it came from. The value averages all kindergarten classes at the school, immersion and neighborhood alike.
7. District enrollment by grade, October 2022
We read these from the district summary page of the October 2022 enrollment profile: kindergarten 3,152; grades 1–5: 3,376, 3,319, 3,502, 3,485, 3,358. We summed the October 2024 and 2025 district kindergarten totals from source 2.
8. Scenario sites and program moves
export_dli_tables.mjs runs the map project’s own code on its data, so these tables match the map:
- Sites. We look at each scenario (status quo, A, B) and grade band (K-5, 6-8, 9-12). A school is a site for each immersion language its label on that map names (“Rigler K-5 Spanish Immersion”; “Roseway Heights Middle School Spanish Immersion, Vietnamese Immersion”). Each scenario site is marked kept or added compared with the status quo. Status-quo sites missing from a scenario are recorded as removed.
own_arearecords whether the school has its own attendance area on that map. - Moves. The table lists every language program move in the memo transcription, with the grade band whose maps show both ends. It also includes one grade change that carries an immersion strand (an immersion program inside a school that also has a neighborhood program): César Chávez becomes K-5, and its grades 6-8, with their Spanish immersion students, move to George.
- Checks. A memo move or grade change explains every site removed in a scenario. School names match source 1 (Brentwood appears as “Lane” in PPS enrollment reports).
9. Home language by census tract
- Tables. American Community Survey (ACS) table B16001 lists Russian and Japanese separately, but it is published only for states. Its tract and county values are blank. So tract counts come from C16001, which reports Spanish, Chinese (including Mandarin and Cantonese) and Vietnamese separately. We approximate Russian with “Russian, Polish or other Slavic languages”, which in Portland also includes Ukrainian speakers. Japanese falls inside “Other Asian and Pacific Island languages” and has no tract count. School-age (5–17) counts come from B16007. It separates only Spanish, other Indo-European, Asian and Pacific Island, and other languages.
- Which tracts. We used tracts in Multnomah, Washington and Clackamas counties whose interior point (
sf::st_point_on_surface) falls inside the district: 135 tracts. We define the district as the union of the status-quo high school attendance areas. - Margins of error. ACS counts are survey estimates. We save each estimate’s margin of error next to it in
acs_language_tract.csv. Margins are large for small groups and single tracts, so tract figures are approximate. District totals are more reliable.
How we calculate each figure and table
Matching school names across sources
School names differ across sources: “Dr. Martin Luther King Jr.” in the memo, “MLK Jr” in enrollment reports, “Cesar Chavez” in lottery reports. All joins use a normalized key, the same one the map uses. To build it, we remove grade and school-type words, strip accents, lowercase letters and drop other characters. A short alias list handles the rest (MLK variants → mlkjr, Lane → Brentwood).
Kindergarten lottery demand (demand chart, waitlist chart, scorecard lottery columns, overview tile 2)
- For each school and lottery year, take the elementary immersion rows for kindergarten (or with no grade printed). Use the printed school total row in years that print one. Otherwise, sum the applicant-group rows.
- Five-year average = mean over the 2022-23 to 2026-27 lotteries in which the program appears. We leave out the 2021-22 lottery because its immersion rows have no grade.
- Overview tile 2 = applications to the Spanish programs that move in Scenario A ÷ all Spanish kindergarten applications. Both are summed over the same five lotteries.
- Counts are applications, not children. A family can apply to several programs, so one child can be waitlisted at more than one school.
- At Lent and Rigler, neighborhood children enroll without applying. These are all-immersion schools with their own neighborhoods. So lottery numbers there count only families from outside the neighborhood. Lent enrolled 43 immersion kindergartners in October 2025 but made 14 lottery offers. Rigler enrolls 50–57 a year and never appears in the lottery. At every other immersion school, including Richmond (which has no neighborhood of its own), October kindergarten enrollment is close to the number of lottery offers.
Who is waitlisted (2026-27 table)
We summed the applicant-group rows from the 2026-27 kindergarten report by residence and by the language background PPS records (English, Heritage, Native). The residence groups are:
- NH = lives in the host school’s attendance area
- RG = lives in the regional Spanish immersion area (the set of schools that feed a high-school Spanish immersion program)
- TR = lives elsewhere in PPS.
The table shows the four Spanish programs with the most waitlisted applications.
Scorecard of program moves
- Students: October 2025 enrollment (source 2) in the moving language program at the sending school, in the grades of the move’s band (K–5 or 6–8).
- K lottery, per year: the five-year averages above, shown only for K-5 moves.
- Home language matches: among a program’s immersion students in October 2025 (source 3), the share whose home language is the program language. For Mandarin, it is the share whose home language is any Chinese language. We show it for the sending program and for the receiving school’s existing program in that language.
- Scenario: “A & B” when the move appears in both scenarios’ memo transcription, otherwise the one it appears in.
Sites by language and grade band
Count of sites (source 8) for each language, grade band and scenario, not counting removed rows.
Distance to the nearest site (table, overview tile 4)
ACS language counts exist only for whole census tracts (about 4,000 residents each). A tract can be over a mile across. So for a 1-mile measure, it matters where inside a tract we place people.
- Spread each tract’s speakers over its census blocks. Census blocks are the smallest areas the Census Bureau counts, often a single city block. We divide each tract’s count among its 2020 census blocks in proportion to block population. For the age 5+ counts we use all residents (2020 Census table P1). For school-age Spanish speakers we use residents under 18 (P1 total minus P3 adults). This assumes speakers are spread like the population within each tract. There are 10,866 blocks in the 135 district tracts.
- Distance. For each block, we measure the straight-line distance in miles from its interior point to the nearest K-5 site of that language. We use Oregon North state-plane coordinates (EPSG:2838) and measure for the status quo and each scenario.
- Within 1 mile = speakers in blocks within 1 mile ÷ all speakers of that language in the district. Average distance = mean distance weighted by speakers.
Checks on the headline figure (school-age Spanish speakers within 1 mile of a K-5 Spanish site), from data-raw/check_access_robustness.R:
- Placement. The first version of this site put each tract’s whole population at one interior point. That gave 59% → 35% at 1 mile. The figure was sensitive to the threshold: at half a mile it gives 12%, because several large tracts sit just inside a mile from a site. Spreading speakers over blocks gives 52% → 36% and changes more smoothly with distance. It is the figure we use.
- Survey error. We redrew each tract’s school-age Spanish count 2,000 times and recomputed the share each time. Each draw comes from a normal distribution with the count’s ACS standard error (90% margin of error ÷ 1.645, floored at zero). 90% intervals: status quo 44–57%, Scenarios A and B 29–41%, drop 11–20 percentage points.
- Plausibility of the counts. The ACS estimates 4,027 (±676) school-age Spanish speakers in the district’s tracts, 7.0% of all residents aged 5–17. PPS counted 3,081 students with Spanish as their home language in October 2025, 7.1% of its enrollment. The ACS figure is larger because it also includes children in private and charter schools.
- Sites. Today’s K-5 Spanish sites: Ainsworth, Atkinson, Beach, César Chávez, James John, Lent, Rigler, Scott, Sitton. Scenarios A and B: Ainsworth, César Chávez, Lent, Rigler. Locations are the school icons on the PPS scenario maps (source 8).
- Limits. Straight-line distance understates real travel, especially across freeways and rivers. The within-tract spread assumes speakers live where the general (or child) population does. We still publish tract-level distances (
access_tract.csv) for mapping.
Bridger → Lent precedent
- Immersion students per grade = each school’s Spanish immersion total (source 1) ÷ 6, since both schools served K–5 in the years used. Before October 2024, PPS doesn’t publish immersion enrollment by grade. So this is an average across grades; an actual kindergarten class can be larger or smaller.
- Kindergarten (actual) = October kindergarten enrollment in Spanish immersion (source 2), 2024-25 and 2025-26.
- Estimated kindergarten immersion classes = kindergarten immersion students (actual where published, otherwise the per-grade average) ÷ the school’s average kindergarten class size (source 6).
- Change = average actual kindergarten immersion enrollment at Lent in 2024-25 and 2025-26 ÷ average combined per-grade immersion enrollment of Bridger and Lent in 2021-22 and 2022-23, minus 1.
- District comparison, same baseline: The before side for Lent is an average across grades K–5. PPS kindergarten classes are smaller than grades 1–5 (October 2022: 3,152 kindergartners vs 3,319–3,502 in each of grades 1–5). So the district comparison also uses an all-grades baseline: average district kindergarten enrollment in October 2024 and October 2025 (source 2) ÷ the average enrollment per grade across grades K–5 in October 2022 (source 7), minus 1. We also report the kindergarten-to-kindergarten district change for reference.
- We deliberately don’t use lottery applications here. Before 2023, Lent’s neighborhood families applied for immersion through the lottery. Afterward they enroll directly. So before and after counts measure different groups.
Overview page tiles
- K-5 Spanish immersion sites on the status-quo map and on the Scenario A and B maps (source 8).
- See Kindergarten lottery demand, step 3.
- Sum of Students (scorecard definition) over every move in Scenario A, including the César Chávez grade change.
- See Distance to the nearest site, for school-age Spanish speakers.
Equity page: who the changes affect
data-raw/equity_analysis.R produces these tables:
equity_changes.csv(one row per closure or immersion move)equity_groups.csv(group totals)equity_home_distance.csvandequity_home_distance_summary.csvequity_home_sensitivity.csv.
PPS’s subgroup table (source 11) is reproduced as printed. The slide gives no year and does not define a “move”. The district-wide comparison sheet labels the same totals “students who would change schools”. It describes figures as 2031-32 projections unless noted. PPS doesn’t say whether it counts students whose immersion program relocates.
Groups compared.
- Immersion program moves: every language program move in a scenario (source 8), plus the César Chávez grades 6–8 Spanish strand moving to George. For each one, we count October 2025 enrollment in that language program at the sending school, in the grades that move (source 2).
- School closures (non-immersion students): for every school the scenario closes (source 8), the October 2025 enrollment in its non-immersion programs (source 3). Immersion students at closing schools (Beach, James John, Rose City Park in A) are counted once, under their program’s move.
- All PPS students: October 2025 district enrollment (source 3).
Neither group includes boundary changes, which move most students in PPS’s totals. No public data gives the students or home languages in each area that changes.
Home language. For each immersion move, we apply the home-language mix of the sending program’s immersion students (all grades of that program) to the students who move. For closures, we use the mix of the school’s non-immersion students. “Non-English” is any home language other than English.
How far the school moves. We use the straight-line distance between school locations on the scenario maps. Some closing schools have attendance areas split among several receiving schools. For those, we weight the distance to each receiving school by the share of the closing school’s attendance area (by land area) that it receives on the scenario map. We ignore receiving areas under 2% of the closing area.
Home-to-school distance (estimate). We place children by census block, using 2020 population under 18 (source 10).
- Closures: blocks inside the closing school’s status-quo attendance area (same grade band). Before = distance to the closing school. After = distance to the school whose attendance area contains the block on the scenario map.
- Immersion moves: PPS doesn’t publish immersion families’ addresses. So we assign each block to its nearest current immersion site of the same language and grade band. This is a catchment by proximity: the area closer to that site than to any other. We use the blocks assigned to the sending program. Before = distance to the sending school; after = distance to the program’s new school. For Spanish, a second version weights blocks by school-age Spanish speakers (ACS tract counts spread over blocks by population under 18).
- Within each change, we average distances over children. Averages across changes are weighted by each change’s enrolled students.
- Sensitivity (
equity_home_sensitivity.csv): we recompute the immersion estimate three ways:- excluding Vietnamese (whose catchment is the whole district)
- for Spanish programs only
- for Spanish programs, weighting blocks by school-age Spanish speakers.
- Limitations:
- The distances are straight-line.
- Proximity catchments are only a model of where immersion families live. Immersion students often come from a wider area. For languages with a single site, such as Vietnamese, the catchment is the whole district.
- The estimate leaves out moves of whole attendance areas between neighborhood schools by boundary change.
Race and ethnicity. Until October 2026, the only school-level race report we used (source 12) gave whole schools. Source 23 is PPS’s Enrollment Summary by Race and Ethnicity for October 2025. It gives each school’s immersion program and neighborhood program separate rows. We use it for the race and ethnicity of students in moving programs (see below). PPS still publishes income (direct certification) for whole schools only.
Equity page: school composition, demand and families not following
School composition (source 12). For each scenario, we sort schools into three groups:
- losing an immersion program: the sending school of any program move or the César Chávez grade change
- receiving an immersion program: receiving schools that are not also sending
- closing with no immersion program: closing schools that are not also sending.
Each school is in one group. Beach, James John and Rose City Park close and lose an immersion program, so they count as losing an immersion program. Percentages are October 2025 School-row values, weighted by enrollment. The district row is PPS’s Grand Total. These figures describe whole schools. For race by program, see below; PPS does not report income by program. Clark is not printed in either year’s report, so we leave it out (the report’s level subtotals include it).
- Historically underserved, per the report’s footnote: “Latino, African American, Native American, Pacific Islander and Multi-Racial Other Ancestries.”
- Direct certification: per the footnote, students the state has identified as eligible for free meals. Paper applications are excluded.
- Parsing checks:
- race shares sum to 98–102% per row
- school enrollment matches source 2 for all 79 schools
- the immersion share × enrollment matches source 1 within rounding
- level subtotals plus program rows equal the grand total (43,479 in October 2025).
Multilingual learners in moving programs (source 1). Students who are both multilingual learners and immersion students ÷ immersion students. We sum over the sending programs (whole program, all grades), October 2025.
Demand at moving programs (source 4). Five-year average kindergarten lottery applications, offers and waitlist for each moving K-5 program (see Kindergarten lottery demand above). Applications per offer is the ratio of the averages.
Families not following a moved program (estimate). Students = October 2025 enrollment in each moving program, in the grades that move. Kindergartners = October 2025 kindergarten immersion enrollment at each sending K-5 program. We apply three assumptions:
- 0%: everyone follows.
- 7%: a public commenter at the October 6, 2026 board meeting (source 14) attributed this figure to “PPS’s own estimate” of affected families leaving the district. We did not find it in PPS documents or staff remarks. It concerns leaving the district, not leaving a program. We show it for comparison only.
- The Bridger → Lent precedent: 1 − (Lent kindergarten immersion ÷ prior Bridger + Lent immersion per grade) ÷ (district kindergarten ÷ prior district per-grade enrollment). That is 1 − 0.69 / 0.86 ≈ 20%.
The precedent rate comes from one consolidation; other programs could fare better or worse. PPS’s equity audit (source 13) found that students already enrolled in moved programs who stayed in PPS generally followed their program. So the loss in the precedent is likely concentrated among new kindergarten families. The six-year total multiplies the yearly kindergarten figure by six. It ignores students who enter or leave in later grades.
Forecast check (sources 5 and 15). For Lent, the 2023-24 forecast edition (June 2023, built on October 2022 enrollment) includes the move: “Bridger Spanish DLI (grades K-5) moved to Lent ES” (Appendix C, note 3). We compare its Lent forecasts for 2023-24 to 2025-26 with PSU’s own October actuals for those years, taken from the 2026-27 edition. The 2022-23 edition predates the move (“These changes are not incorporated in these enrollment forecasts”). So we add its Bridger and Lent Spanish rows together as the pre-move program. District totals from the same editions show the size of a typical forecast miss.
- Actuals are kindergarten through grade 12. PPS’s own school totals for Lent include pre-kindergarten (308 in October 2023 vs PSU’s 273), so we don’t mix the two.
- Text-layer checks: In the 2023-24 edition, runs of zeros merge in the text layer, and a few rows are garbled (not Lent). We decoded those rows from school totals minus the other program rows. The subtotals and the TOTAL row then reconcile.
- Limits: Forecasts made one or two years ahead also miss for ordinary reasons. Other schools’ Spanish programs missed by up to 10–27% in either direction (Rigler and Atkinson were under-forecast). So Lent’s miss is notable for its size and persistence, not unique.
- No edition states an assumed share of students following a moved program. The 98% figure (314 of 319) is implied by the numbers.
Race and ethnicity by program (source 23)
Reading the report. The PDF has 6 pages. Pages 1 to 5 list every school and program; page 6 is a footnote. In the PDF’s text layer, the Native American count drops out of its row. So parse_race_by_program.py reads each cell by its position on the page (PyMuPDF word coordinates). It assigns each cell to a column by its right edge. Empty cells are zero. The script checks that:
- the eight counts in each row add up to the row total
- each printed percentage equals 100 × count / total, within 0.05
- each school’s immersion and neighborhood rows add up to its total row
- the schools in each section add up to the section total, and the sections to the district total (43,477)
- no school and program appears twice.
All 189 rows pass. Whole-school totals match source 12 at 79 schools; Richmond differs by one student (511 vs 512).
Groups. Latino includes students of any race; the other seven groups are not Latino, as in PPS’s report. Per the report’s footnote, “Latino ethnicity includes students identified as Hispanic/Latino regardless of race. Multiple Races category includes students identified as two or more races, exclusive of Hispanic/Latino.”
So the single-race groups count only students who list one race and are not Latino. A Native American student who is also Latino counts as Latino, and one who lists two races counts as multiracial. The counts for small single-race groups, especially Native American and Pacific Islander students, are therefore minimums for those communities. Historically underserved follows PPS’s definition (source 12): Latino, Black, Native American, Pacific Islander and multiracial “other ancestries”. It leaves out Asian and Asian/White students, so we report every group separately as well.
Who would have to change schools (equity_race.R → equity_race_groups.csv):
- Immersion program moves: each moving program’s immersion row. Whole programs match the October 2025 grade counts (source 2) exactly. César Chávez’s grade 6-8 move takes only part of a K-8 program. We apply the K-8 program’s mix to its 105 grade 6-8 students.
- Closures: students outside immersion at each closing school (its neighborhood row, or the school row if it has no immersion program). These match the closure counts in
equity_changes.csvexactly. - César Chávez neighborhood program: in both scenarios César Chávez becomes a K-5 Spanish immersion school, and its guide says “Neighborhood (non-DLI) K-5 students would move to Rosa Parks K-5. Middle grade (6th-8th) students would move to George Middle School” (source 16, page 3). We count its whole neighborhood row (143 students), and we include them in the §1 count of directly displaced students.
- Comparisons: PPS’s elementary and middle school section totals, since every move and closure is in grades K-8. We also total every K-8 immersion row, including whole-school immersion schools.
Each moving program (equity_race_programs.csv) compares the program with its school’s neighborhood row. PPS’s projected share of students from underserved racial groups (equity_race_schools.csv) comes from each school guide (source 16). The page 4 table, “Who would the school serve?”, gives it with no changes and under each option. Those projections include boundary changes and every other change at the school. So we can’t trace them to the program move alone. PPS’s figure for a school today matches the share we compute from source 23 (Atkinson: 44.0% vs 161 of 366).
Figures. Four figures in Equity §3 show the same numbers as the tables, for Scenario A (R/race_charts.R):
- Who would have to change schools, by race and ethnicity: shares from
equity_race_groups.csv, with all PPS elementary and middle schools as the reference. - Immersion program vs neighborhood program: Black and Latino shares from
equity_race_programs.csv. - Black students who would have to change schools: counts by school or program from
equity_race_black.csv. They add up to the group totals; the script stops if they don’t. The figure leaves out rows with fewer than one student. - PPS’s projected share from underserved racial groups:
equity_race_schools.csv.
The figures use the site’s three tested colors in a fixed order. Blue marks program moves, orange marks closures and aqua marks César Chávez’s neighborhood program. Each also has its own marker shape, so color is never the only cue. A hollow gray ring marks the comparison or “no changes” value.
Limitations. These are October 2025 counts, before any move. They describe the students enrolled now, not those who would follow a moved program. Groups with few students (Native American, Pacific Islander) are too small for program-by-program percentages. The history paragraph on the Equity page quotes source 24 directly.
Lent’s 2023 projection and staff accounts (sources 13 and 17)
We quote the 527-student projection from the appendix’s summary of PPS’s Phase 2 school-by-school impact analysis (appendix p. 34). The appendix cites that analysis as “Portland Public Schools. (n.d.). SE enrollment and program balancing phase 2 school-by-school impact analysis”, p. 12. The appendix calls it “Lent’s total enrollment” and does not say whether pre-kindergarten is included. We compare it with October 2025 kindergarten–5th grade enrollment (source 2). Staff and family quotes are verbatim from the appendix and the main report, with page numbers. The ellipses and brackets are the report’s own. The report identifies speakers only by school and role.
Neighborhood capture rates (source 18)
A capture rate is the share of students living in an attendance area who attend their own neighborhood school. Each report gives, for every attendance area, the PPS K-12 students living there by the type of school they attend:
- their own neighborhood school (the capture rate)
- another neighborhood school
- a PPS alternative
- a community-based alternative
- special services
- a PPS charter.
Pre-kindergarten is excluded. Immersion students attending their own area’s school count as captured. Immersion students attending another school’s program count under “other neighborhood school” or “PPS alternative”.
- Parsing checks: Categories sum to each row’s total. Printed percentages match counts (±0.51). Level totals and the grand total (29,036 of 42,622 in October 2025) match the sums of their rows. Every year 2019-20 to 2025-26 uses the same layout.
- Groups (
equity_capture.csv): Southeast = the elementary areas of Abernethy, Atkinson, Bridger (Bridger Creative Science from 2023-24), Creston, Duniway, Grout, Lewis, Llewellyn, Sunnyside Environmental, Woodstock, Marysville, Kelly, Arleta, Whitman and Woodmere. Lent is shown separately. Rest of PPS = all other elementary areas. Group rates are total own-school students ÷ total residents. - Limits:
- Boundaries changed in 2021-22 and 2023-24, so areas’ resident counts jump.
- Students allowed to stay at their former school after a boundary change count as “other neighborhood school”.
- Creative Science (a focus school) moved into the Bridger building in 2023-24.
- Lent’s non-immersion neighborhood children were assigned to Marysville after 2023, which the report counts as “other neighborhood school”.
Checking the home-to-school model against where students live (source 19)
The School Enrollment by Neighborhood of Residence report gives, for each school and program, the students living in the school’s own attendance area. It then sorts everyone else by the high-school area they live in (Cleveland, Franklin, Grant, Ida B. Wells-Barnett, Jefferson/Grant, Jefferson/McDaniel, Jefferson/Roosevelt, Lincoln, McDaniel, Roosevelt), plus out-of-district or undetermined. Pre-kindergarten is excluded.
Parsing checks:
- cells sum to row totals
- printed percentages match (±0.51)
- program rows sum to school totals, and schools to section and grand totals
- own-area counts equal the capture-rate report for all 53 elementary schools in each year
- October 2025 school × program totals equal source 2 for all 142 rows.
check_home_distance.R places each moving program’s students on 2020 census blocks. Own-area students go in the school’s status-quo attendance area. Others go in their high-school area, outside the school’s own area. The Jefferson sub-areas have no published boundaries. So we assign Jefferson-area blocks to whichever of the Grant, McDaniel and Roosevelt areas is nearest. Within an area, we spread students in one of two ways: like children under 18 (area average), or over only the half of the area’s children living closest to the program’s current school (nearer half). We leave out out-of-district and undetermined students. Moves are averaged with the same weights as the model (students in the grades that move).
- Limits: High-school areas are large, so students living outside their school’s area are placed only roughly. César Chávez’s row covers grades K-8, though only grades 6-8 move to George. Distances are straight-line.
Southeast seats, demand and site context (sources 2, 4, 9, 10, 19)
- Kindergarten seats = October 2025 kindergarten enrollment (source 2): Richmond and Le Monde whole school; Lent and Atkinson Spanish immersion. Program students = all grades of the same programs. Lottery columns are the five-year averages defined above. Le Monde is a charter with its own admissions and isn’t in the PPS lottery reports.
- Southeast Spanish means the two Spanish immersion sites in the Franklin and Cleveland high-school areas: Lent and Atkinson.
- Miles to district edge: straight line from the school’s location on the status-quo map (source 8) to the boundary of the union of the high-school attendance areas.
- Own area: Spanish immersion students living in the school’s own attendance area (source 19). Rigler and Lent are whole-school.
- School-age Spanish speakers within 1.5 miles: ACS tract counts spread over census blocks by population under 18 (sources 9 and 10), summed over blocks within 1.5 miles.
- Capacity (source 21): functional capacity = permanent and modular classrooms × PPS station size (students per classroom), minus set-asides, as printed in the 2021 plan. Parsing checks: every row has three counts and five utilization percentages, and all 71 sites match meub/pps-data’s independent parse. We show the 2021 figures for comparison only.
- Current capacity (source 22) is PPS’s 2025-26 functional capacity from its School Profiles dashboard. It differs from 2021 for many buildings (Atkinson 519 vs 567, Lent 798 vs 707, Creston 429 vs 558, Rigler 621 vs 589).
- Share of capacity = October 2025 K-5 enrollment (source 2), or PPS’s 2027-28 Scenario A projection (source 16), ÷ current functional capacity.
- Room per grade = (capacity − enrollment) ÷ 6 grades.
- Distance from Atkinson: straight line between school locations on the status-quo map (Creston 0.8 mi, Lent 2.4 mi).
- Creston’s seismic status (unreinforced masonry, targeted for retrofit) is from the PPS facility data compiled in meub/pps-data. We did not check it against PPS’s bond documents.
- Richmond’s point on the original pps-explorer map was a copy of Atkinson’s (SE 58th & Division). We corrected it in this copy to the Census Bureau geocode of its address, 2276 SE 41st Ave, just north of Division. The map on the School changes page uses the corrected point.
Freeway air (Equity §10)
data-raw/freeway_distance.R measures how far each school is from a freeway. data-raw/freeway_equity.R joins those distances to the plan.
- Freeways. OpenStreetMap ways tagged
highway=motorway(I-5, I-84, I-205, I-405, US 26, OR 217 and parts of US 30). We report ramps (motorway_link) separately. - School grounds. The OpenStreetMap school polygon that contains each school’s map point. When a point sits just outside its grounds, the script uses the nearest school polygon within 30 m (Peninsula, 1 m). OpenStreetMap tags Cleveland High’s grounds as a former school; we use them anyway. The script stops if any school has no grounds.
- Distance. The shortest straight-line distance from the edge of the grounds to the nearest freeway segment, in meters, in UTM zone 10N (EPSG:32610). It is 0 if they touch. We also report the distance from the map point, which is roughly the building.
- Bands. Within 150 m (500 feet), where the EPA says near-road pollution is highest; 150 to 600 m; and over 600 m (2,000 feet), about background.
- Check. A first run done by hand in a browser gave the same grounds for all 82 schools and distances within 7 m.
- Moves. Each group in
plan_flows.csvgets its current and new school’s distance. A group “moves within 150 m” when its new school is within 150 m and its current school is not. - K-8 only. Counts and shares cover students in kindergarten through grade 8, like the School changes page. The “with high school students” note adds the high schools back, using the same race report. No high school student moves to or from a freeway school in the plan.
- Race and ethnicity. These come from the same program-level counts as the rest of the School changes analysis, before any count is hidden. The tables hide counts under 5 (#small-numbers).
- Limits. OpenStreetMap grounds are drawn by volunteers and may include fields or parks. Distance is not exposure. We don’t model wind, terrain, sound walls, traffic volume or trucks, and we don’t count busy streets that aren’t freeways. Student counts are today’s students moved all at once.
School changes page
data-raw/school_changes.R builds every number on the School changes page except the special education section, which data-raw/sped_programs.R builds.
Where students go. data-raw/plan_flows.csv has one row for each group of current students that would change buildings. Each row names the sending school, the part that moves and the receiving school. The part is the whole school, the neighborhood program, an immersion program, or grades 6-8. Each row also gives the share that moves and the sentence in PPS’s school guide it rests on (page 3, “What is being proposed?”). Four rows rest on our assumptions rather than a PPS share:
- Marysville. PPS splits Marysville between Arleta and Kelly. We send all of it to Arleta, because PPS projects Arleta would grow by 333 students by 2031-32 and Kelly by 10.
- Sellwood. PPS sends the Llewellyn area to Hosford and the Duniway and Lewis areas to Brentwood. We split Sellwood’s students by the enrollment of those elementary schools: 36% to Hosford and 64% to Brentwood.
- Odyssey. Its program moves into Metropolitan Learning Center’s building. We count it as a program that moves, not a closure, so the closure counts match PPS’s (14 in Scenario A, 11 in B).
- Lee is now Sunrise. PPS’s October 2025 race report calls the school at 2222 NE 92nd Ave “Lee”. The guides and the 2026-27 Title I list call it Sunrise.
Race and ethnicity. Each part’s race and ethnicity comes from source 23. Some K-8 schools send only grades 6-8. For these, we scale the school’s row by the share of its October 2025 students in those grades (source 2). This assumes the same mix in every grade. A school’s mix after the move is its students today, minus the parts that leave, plus the parts that arrive.
Roles. “Closes” uses PPS’s guides (“School would close”) plus Sellwood, which closes in 2028. “Takes in students” means at least one part arrives. “Sends students away” means at least one part leaves but the building stays open. “Boundary or feeder change only” means PPS’s guide lists a change, but no current student moves (for example, future middle schoolers from Kelly going to Harrison Park).
K-8 only. The School changes page counts students in kindergarten through grade 8, the students this site is about. It leaves out high schools and Metropolitan Learning Center’s grades 9-12, whose students we remove using its October 2025 grade counts (source 2). The “with high school students” notes add them back from data/plan_high_school_students.csv. High schools change only through boundaries and feeder schools for future students. The one exception is Metropolitan Learning Center’s grades 9-12, which end; those students choose another school.
Students the plan affects. The table at the top of the page counts each K-8 student once, by October 2025 enrollment. Students change buildings if their school closes, if Odyssey’s program moves, or if their program or grades leave a school that stays open. The others at a school that takes in students count as staying at a school that takes in students. The others at a school that only sends students away count separately. The last row adds every student at a school with only a boundary or feeder change. The total equals all students at schools the plan changes in any way. The page stops building if it doesn’t (plan_affected() in R/plan_charts.R).
The tables below show the same counts school by school. Each group’s subtotal is one row of the table on the School changes page:
- “Change buildings” adds the subtotals of that column: closing schools, Odyssey, and the students who leave schools that take in or send away students.
- “Stay” at schools that take in students and at schools that only send some away are the two “stay” rows.
- The boundary and feeder group is the last row. All of its students stay.
“Arriving” (students arriving from other schools) is for reference only. We count each moving student once, at the school they leave. Arrivals (6,901 in Scenario A) and students who change buildings (6,900) can differ by a student or two. Some groups split between two schools, and we round each part.
| School | Today | Change buildings | Stay | Arriving |
|---|---|---|---|---|
| Closes | ||||
| Beach | 288 | 288 | 0 | 0 |
| Buckman | 283 | 283 | 0 | 0 |
| Creston | 213 | 213 | 0 | 0 |
| Irvington | 259 | 259 | 0 | 0 |
| James John | 365 | 365 | 0 | 0 |
| Lewis | 259 | 259 | 0 | 0 |
| Maplewood | 287 | 287 | 0 | 0 |
| Marysville | 307 | 307 | 0 | 0 |
| Peninsula | 239 | 239 | 0 | 0 |
| Rose City Park | 417 | 417 | 0 | 0 |
| Sabin | 269 | 269 | 0 | 0 |
| Sellwood | 564 | 564 | 0 | 0 |
| Stephenson | 281 | 281 | 0 | 0 |
| Woodmere | 227 | 227 | 0 | 0 |
| Subtotal | 4,258 | 4,258 | 0 | 0 |
| Program moves to another building (Odyssey) | ||||
| Odyssey | 217 | 217 | 0 | 0 |
| Subtotal | 217 | 217 | 0 | 0 |
| Takes in students (some also send students away) | ||||
| Abernethy | 269 | 0 | 269 | 142 |
| Arleta | 230 | 0 | 230 | 307 |
| Atkinson | 366 | 178 | 188 | 213 |
| Beaumont | 416 | 101 | 315 | 204 |
| Beverly Cleary | 480 | 204 | 276 | 259 |
| Boise-Eliot/Humboldt | 294 | 0 | 294 | 193 |
| Brentwood | 447 | 0 | 447 | 361 |
| Capitol Hill | 325 | 0 | 325 | 84 |
| Chief Joseph | 242 | 0 | 242 | 133 |
| César Chávez | 443 | 248 | 195 | 426 |
| Duniway | 362 | 0 | 362 | 259 |
| George | 358 | 0 | 358 | 233 |
| Harriet Tubman | 402 | 0 | 402 | 196 |
| Harrison Park | 419 | 0 | 419 | 140 |
| Hayhurst | 290 | 0 | 290 | 201 |
| Hosford | 528 | 0 | 528 | 396 |
| Lent | 256 | 0 | 256 | 178 |
| MLC | 234 | 0 | 234 | 217 |
| MLK Jr. | 319 | 193 | 126 | 269 |
| Markham | 339 | 0 | 339 | 197 |
| Mt. Tabor | 430 | 0 | 430 | 235 |
| Ockley Green | 460 | 63 | 397 | 223 |
| Rieke | 264 | 0 | 264 | 86 |
| Rigler | 289 | 0 | 289 | 222 |
| Rosa Parks | 160 | 0 | 160 | 317 |
| Roseway Heights | 572 | 0 | 572 | 101 |
| Scott | 476 | 222 | 254 | 210 |
| Sitton | 345 | 138 | 207 | 232 |
| Sunnyside | 485 | 193 | 292 | 142 |
| Vestal | 283 | 0 | 283 | 207 |
| Whitman | 194 | 0 | 194 | 227 |
| Woodstock | 367 | 0 | 367 | 91 |
| Subtotal | 11,344 | 1,540 | 9,804 | 6,901 |
| Only sends some students away | ||||
| Bridger | 446 | 140 | 306 | 0 |
| Clark | 364 | 91 | 273 | 0 |
| Faubion | 600 | 223 | 377 | 0 |
| Laurelhurst | 610 | 235 | 375 | 0 |
| Vernon | 541 | 196 | 345 | 0 |
| Subtotal | 2,561 | 885 | 1,676 | 0 |
| Boundary or feeder change only | ||||
| Astor | 400 | 0 | 400 | 0 |
| Glencoe | 339 | 0 | 339 | 0 |
| Gray | 432 | 0 | 432 | 0 |
| Jackson | 689 | 0 | 689 | 0 |
| Kellogg | 531 | 0 | 531 | 0 |
| Kelly | 411 | 0 | 411 | 0 |
| Llewellyn | 345 | 0 | 345 | 0 |
| Skyline | 207 | 0 | 207 | 0 |
| Subtotal | 3,354 | 0 | 3,354 | 0 |
| All schools the plan changes | 21,734 | 6,900 | 14,834 | 6,901 |
| Sources: where each school’s students would go: PPS, How Could Your School Be Impacted? school guides (per-school PDFs dated October 8, 2026), page 3, “What is being proposed?” (page); every sentence used is in data-raw/plan_flows.csv; PPS, How Could Your School Be Impacted? school guides (per-school PDFs dated October 8, 2026), page 4, “Who would the school serve?”, column “Underserved racial groups”, with no changes and under each option (page); PPS, Enrollment Summary by Race and Ethnicity, October 2025 (separate rows for each school’s immersion and neighborhood programs; PDF), retrieved October 11, 2026. Method details: Sources & methods. | ||||
| School | Today | Change buildings | Stay | Arriving |
|---|---|---|---|---|
| Closes | ||||
| Beach | 288 | 288 | 0 | 0 |
| Buckman | 283 | 283 | 0 | 0 |
| Creston | 213 | 213 | 0 | 0 |
| Irvington | 259 | 259 | 0 | 0 |
| James John | 365 | 365 | 0 | 0 |
| Maplewood | 287 | 287 | 0 | 0 |
| Marysville | 307 | 307 | 0 | 0 |
| Peninsula | 239 | 239 | 0 | 0 |
| Sabin | 269 | 269 | 0 | 0 |
| Sellwood | 564 | 564 | 0 | 0 |
| Woodmere | 227 | 227 | 0 | 0 |
| Subtotal | 3,301 | 3,301 | 0 | 0 |
| Program moves to another building (Odyssey) | ||||
| Odyssey | 217 | 217 | 0 | 0 |
| Subtotal | 217 | 217 | 0 | 0 |
| Takes in students (some also send students away) | ||||
| Abernethy | 269 | 0 | 269 | 142 |
| Arleta | 230 | 0 | 230 | 307 |
| Atkinson | 366 | 178 | 188 | 213 |
| Beaumont | 416 | 101 | 315 | 204 |
| Beverly Cleary | 480 | 204 | 276 | 259 |
| Boise-Eliot/Humboldt | 294 | 0 | 294 | 193 |
| Brentwood | 447 | 0 | 447 | 361 |
| Chief Joseph | 242 | 0 | 242 | 133 |
| César Chávez | 443 | 248 | 195 | 426 |
| George | 358 | 0 | 358 | 233 |
| Harriet Tubman | 402 | 0 | 402 | 196 |
| Harrison Park | 419 | 0 | 419 | 140 |
| Hayhurst | 290 | 0 | 290 | 201 |
| Hosford | 528 | 0 | 528 | 396 |
| Lent | 256 | 0 | 256 | 178 |
| MLC | 234 | 0 | 234 | 217 |
| MLK Jr. | 319 | 193 | 126 | 269 |
| Mt. Tabor | 430 | 0 | 430 | 235 |
| Ockley Green | 460 | 63 | 397 | 223 |
| Rieke | 264 | 0 | 264 | 86 |
| Rigler | 289 | 0 | 289 | 222 |
| Rosa Parks | 160 | 0 | 160 | 317 |
| Roseway Heights | 572 | 0 | 572 | 101 |
| Sitton | 345 | 138 | 207 | 232 |
| Sunnyside | 485 | 193 | 292 | 142 |
| Whitman | 194 | 0 | 194 | 227 |
| Woodstock | 367 | 0 | 367 | 91 |
| Subtotal | 9,559 | 1,318 | 8,241 | 5,944 |
| Only sends some students away | ||||
| Bridger | 446 | 140 | 306 | 0 |
| Clark | 364 | 91 | 273 | 0 |
| Faubion | 600 | 223 | 377 | 0 |
| Laurelhurst | 610 | 235 | 375 | 0 |
| Scott | 476 | 222 | 254 | 0 |
| Vernon | 541 | 196 | 345 | 0 |
| Subtotal | 3,037 | 1,107 | 1,930 | 0 |
| Boundary or feeder change only | ||||
| Astor | 400 | 0 | 400 | 0 |
| Glencoe | 339 | 0 | 339 | 0 |
| Gray | 432 | 0 | 432 | 0 |
| Jackson | 689 | 0 | 689 | 0 |
| Kellogg | 531 | 0 | 531 | 0 |
| Kelly | 411 | 0 | 411 | 0 |
| Lewis | 259 | 0 | 259 | 0 |
| Skyline | 207 | 0 | 207 | 0 |
| Subtotal | 3,268 | 0 | 3,268 | 0 |
| All schools the plan changes | 19,382 | 5,943 | 13,439 | 5,944 |
| Sources: where each school’s students would go: PPS, How Could Your School Be Impacted? school guides (per-school PDFs dated October 8, 2026), page 3, “What is being proposed?” (page); every sentence used is in data-raw/plan_flows.csv; PPS, How Could Your School Be Impacted? school guides (per-school PDFs dated October 8, 2026), page 4, “Who would the school serve?”, column “Underserved racial groups”, with no changes and under each option (page); PPS, Enrollment Summary by Race and Ethnicity, October 2025 (separate rows for each school’s immersion and neighborhood programs; PDF), retrieved October 11, 2026. Method details: Sources & methods. | ||||
Check against PPS. PPS’s guides give each school’s projected share from underserved racial groups with no changes and under each scenario (source 16). Our estimate of each school’s change matches the direction and size of PPS’s. The correlation is 0.93 across 70 school-scenario pairs, and the median gap is 1.6 percentage points. The script stops if the correlation falls below 0.8.
Title I and SUN. A school counts as Title I if it is on PPS’s 2026-27 list, including the three bridge schools. PPS’s guides leave bridge schools out of their Title I column, so we use the guides only for the projected status after the changes. The Title I figure counts every student in each group that moves, because PPS runs Title I school-wide. PPS publishes income (direct certification) only for whole schools, so we can’t count the low-income students in each group. SUN status is the county’s August 2026 contact list. The county’s printable SUN map dates from August 2018 and is out of date.
Special education. The script data-raw/sped_programs.R builds the special education section.
- Moves.
data-raw/sped/sped_moves.csvhas one row for each special education program that a PPS guide says would move or stay. Each row quotes the guide (page 3). - Staff. Staff counts come from source 27, a spreadsheet of planned 2026-27 staffing that a board member requested. PPS has not published it as a report. It counts teacher positions and aides, not students. It leaves out the Deaf and Hard of Hearing program, which Columbia Regional Inclusive Services (CRIS) runs with the school.
- Room. PPS describes each SES, CB and ISC classroom as one teacher, 2 or 3 aides and 10 to 12 students. The “room for” estimate assumes one classroom per teacher position. It is room, not a count of children.
- Receiving schools. “Has this kind of classroom today” means the spreadsheet shows at least one position of that type there.
- Checks. The script stops if a school in the spreadsheet doesn’t match the plan tables. It also stops if a closing school with an SES, CB or ISC position has no row in
sped_moves.csv.
Middle grades. data-raw/tle_slides.R enters two tables from source 28. One is kindergarten seats and enrollment by language (DLI slide 4). The other is the K-8 staffing subsidy (middle grades slide 5). The script checks the subsidy table against its printed totals. The K-8 schools that would send grades 6-8 away are the plan_flows.csv rows whose part is grades 6-8. Their student count is October 2025 enrollment in those grades, so it is the size of the change, like the rest of the page. We report the research effects as each study states them. The Florida figures come from the working-paper version of Schwerdt and West. The studies come from New York City, Florida and one unnamed district, not Portland.
Map. The map shows every K-8, middle and alternative school (72 buildings). Each circle’s area is proportional to the school’s students: today, or after each scenario. Its color is the share of students from underserved racial groups, in five bands. A dark ring around the circle marks a school whose share changes by 5 percentage points or more. Schools that close, or whose program moves out, appear as dashed gray rings at today’s size. School locations are pps-explorer’s status-quo points (data/plan_school_points.csv). The map shows only whole-school totals, never a single racial group, so no small count appears. The design draws on the scenario map at ppsdata.info by Alex Meub, which sizes each school’s circle by its enrollment.
Separation by race. For groups a and b, the dissimilarity index is D = ½ Σ |aᵢ/A − bᵢ/B|. The sum runs over the units i in the area. It is the share of either group that would have to move for every unit to match the area’s mix. Exposure is Σ (aᵢ/A)(wᵢ/tᵢ), the white share of the unit attended by the typical student in group a. We compute both with two kinds of unit:
- each building;
- each program, with immersion and neighborhood programs as separate units even in one building.
The areas are all elementary (K-5 and K-8) schools, all middle schools, and three local groups: Northeast (Scott, Rigler, Rose City Park, Vestal), North (MLK Jr., Sabin, Boise-Eliot/Humboldt) and Southeast (Atkinson, Lent, Creston). The local groups have only two to six units, so one school can move the index a lot.
Limits. This is a snapshot: it moves October 2025 students all at once. The changes start in 2027-28 or later, and many of today’s students will have moved on. Sellwood, for example, closes in 2028, after all of its current students have left 8th grade. So the student counts show the size of each change, not the number of children who will move. PPS’s projections are for 2027-28 and later and include future boundary effects and growth. So school sizes here differ from PPS’s. For example, Brentwood and Hosford take in all of Sellwood’s current students at once. Special education and Deaf and Hard of Hearing classrooms are not separated in the race report.
Lent & César Chávez page
data-raw/history_tables.R writes history_enrollment.csv and history_projection.csv.
- Enrollment by program, 2019-20 to 2025-26: October actuals (kindergarten through grade 12) printed in the PSU forecast editions (sources 5 and 15). Each year uses the first edition that prints it. Later editions sometimes restate past years under a school’s new configuration. For example, the 2024-25 edition prints Bridger’s 2021-22 and 2022-23 totals with Creative Science included, and César Chávez’s totals differ by 3 between editions. Spanish immersion counts agree across editions, and the script stops if they don’t. The 2024-25 and 2025-26 figures match PPS’s enrollment report (source 2, excluding pre-kindergarten) exactly.
- Grade configuration: Lent and Bridger were K-8 until 2021-22, so their earlier totals include grades 6-8. César Chávez is K-8 throughout. Bridger is shown only for its Spanish program, which moved to Lent in 2023-24.
- Capture rate and where students live: sources 18 and 19; demographics: source 12, School and Neighborhood rows; projections: source 16; capacity: source 21.
School Profiles dashboard (source 22)
PPS’s School Profiles page embeds a public Power BI report that shows one school at a time. scrape_school_profiles.mjs opens it in headless Chrome (a browser run by a script, with no window). It selects each of the 83 schools in the report’s school list and saves the visible text, with the time retrieved, to data-raw/pps_reports/school_profiles/. parse_school_profiles.py reads those snapshots into school_profiles_2025.csv.
- Checks: Every snapshot has an address, capacity and enrollment, and no address repeats, so no snapshot shows the wrong school. The two capacity tiles agree. Utilization equals enrollment ÷ capacity within 0.6 points. Capture rate equals students in the neighborhood school ÷ PPS students living in the zone within 0.1 point. The dashboard’s 2025-26 enrollment equals PPS’s October 2025 K-12 enrollment, excluding pre-kindergarten (source 2), for all 76 schools in both sources.
- Blanks: We leave blank the values the dashboard abbreviates (for example, “2K” at high schools). Alliance has no building of its own, so its capacity is blank.
- Not used: The dashboard computes capture rate differently from PPS’s capture-rate report (source 18). For example, Lent shows 28.0% (80 of 286 students living in its zone). The site uses source 18 for capture rates. We don’t capture the enrollment and race charts on the dashboard.
Research page
The Whole-school vs. strand page reviews published work on whole-school versus strand immersion. It has no script. Its only computed figures come from two sources. Source 2 gives immersion and neighborhood-program students per grade (K-5, October 2025). Source 4 gives Ainsworth’s lottery average.
- Whole school vs. strand: We count a K-5 site as whole-school when PPS reports no neighborhood-program students in grades K-5 there (Lent, Rigler and Richmond in October 2025). Immersion students per grade is K-5 immersion enrollment divided by six. PPS doesn’t publish classes per program, so this is only a rough guide to class counts.
- Literature: We read each study in full text where it was openly available. That covers:
- Steele et al. (2017, ERIC open manuscript)
- the Utah working paper (2021)
- Watzinger-Tharp et al.
- Bibler’s 2016 working paper
- CAL’s Guiding Principles (3rd ed.)
- RAND briefs RB-9903 and RB-9921
- the National Academies report (all chapters)
- CABE’s planning-guide pages.
- Search for a whole-school vs. strand comparison (October 9, 2026):
- Web and scholarly searches combining “dual language” or “two-way immersion” with “strand”, “whole school”, “school-wide”, “school within a school”, and achievement, attrition or teacher retention.
- Crossref lookups for each cited paper.
- Full-text searches for “strand”, “whole-school”, “school-wide”, “within-school” and “magnet” in every full text listed above.
- ERIC, Google Scholar and JSTOR weren’t queried directly.
- “No study found” means none turned up in this search. Lindholm-Leary (2001) and Thomas & Collier weren’t available in full text.
- Lent outcomes are quoted from the equity audit’s school-by-school analysis (source 17, pp. 39, 45, 47) and main report (p. 50). The underlying student-level data isn’t public.
- PPS statements: the October 6, 2026 board meeting (staff presentation at 2:25:37) and the September 8, 2026 committee meeting (13:15), from the automated transcripts in
data-raw/pps_transcripts/. A search of those transcripts and the per-school guides found no research cited for the model choice.
Small numbers
To protect students’ privacy, this site never shows a racial or ethnic count under 5. This includes zero and our own estimates. Where a group has 0 to 4 students, tables and hover text show “<5”, or a share as “<X%”. X is the share that 5 students would be, rounded up. For example, fewer than 5 of 155 students shows as “<4%”. Figures draw these values near zero with an open marker. On the Equity page, one bar for each reason combines the schools with fewer than 5 Black students.
Someone could sometimes work out a hidden count by subtracting the other groups from the total. So in any row of a data file with exactly one hidden group, we also hide the next-smallest count. The data files our scripts write (equity_race_*.csv, plan_*.csv) leave hidden counts blank and give shares as whole percents. We compute all totals, sums and indexes from the exact numbers before hiding anything.
PPS’s own report prints these small counts. We keep its table (race_by_program_2025.csv, source 23) as PPS published it, so others can reproduce the analysis.
Spanish version
Every page is also published in Latin American Spanish (es/, the Español button). We wrote the translation from the English pages with AI assistance (Claude) and reviewed it for accuracy. The same R code computes every number on the Spanish and English pages, and a check confirms both versions show the same numbers. Quotations from English documents and meetings are our translations. Document titles stay in their original language. Terminology follows es/GLOSSARY.md. If the two versions ever differ, the English page is the reference.
Reproducing the data
Clone the repository and run these commands from its root. You need:
- Python 3 and
pypdf - Node 22
- R with
tidycensus,sf,dplyr,tidyrandreadr - a free Census API key in
CENSUS_API_KEY.
python3 data-raw/parse_immersion_profiles.py
python3 data-raw/parse_program_type.py
python3 data-raw/parse_language_by_school.py
python3 data-raw/parse_lottery.py
python3 data-raw/parse_psu_forecast.py
python3 data-raw/extract_psu_premove.py
python3 data-raw/parse_ethnicity_program.py
python3 data-raw/parse_school_guides.py
python3 data-raw/parse_capture_rate.py
python3 data-raw/parse_enroll_by_neighborhood.py
python3 data-raw/parse_lrfp_capacity.py
node data-raw/export_dli_tables.mjs
Rscript data-raw/acs_language_access.R
Rscript data-raw/check_access_robustness.R
Rscript data-raw/equity_analysis.R
Rscript data-raw/check_home_distance.R
Rscript data-raw/history_tables.R
Rscript data-raw/equity_race.R
Rscript data-raw/school_changes.R
Rscript data-raw/sped_programs.R
Rscript data-raw/tle_slides.R
Rscript data-raw/freeway_distance.R # needs network on first run (Overpass); cached in data-raw/osm/
Rscript data-raw/freeway_equity.R
quarto renderEach parser prints its checks and stops on any failure.