Skip to contents

Oregon enrolls 547,424 students across 210 school districts and 1,423 schools. A decade of growth erased by a pandemic, a kindergarten class that never bounced back, and a rural district that more than doubled while everyone else shrank—there are stories hiding in these numbers.

Part of the njschooldata family.

Full documentation — all 15 stories with interactive charts, getting-started guide, and complete function reference.

Highlights


1. Oregon’s enrollment peaked in 2020, then COVID hit

The state added students for a decade, then lost nearly 22,000 in a single year during the pandemic.

enr <- fetch_enr_multi(2010:2024, use_cache = TRUE)

state_totals <- enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  select(end_year, n_students) |>
  mutate(change = n_students - lag(n_students),
         pct_change = round(change / lag(n_students) * 100, 2))

stopifnot(nrow(state_totals) > 0)
state_totals
#>    end_year n_students change pct_change
#> 1      2010     561696     NA         NA
#> 2      2011     561696      0       0.00
#> 3      2012     561328   -368      -0.07
#> 4      2013     560946   -382      -0.07
#> 5      2014     562262   1316       0.23
#> 6      2015     570857   8595       1.53
#> 7      2016     576407   5550       0.97
#> 8      2017     578947   2540       0.44
#> 9      2018     580684   1737       0.30
#> 10     2019     581730   1046       0.18
#> 11     2020     582661    931       0.16
#> 12     2021     560917 -21744      -3.73
#> 13     2022     553012  -7905      -1.41
#> 14     2023     552380   -632      -0.11
#> 15     2024     547424  -4956      -0.90
Oregon statewide enrollment trends
Oregon statewide enrollment trends

(source)


2. The COVID kindergarten collapse hasn’t recovered

Kindergarten enrollment dropped 14.6% from 2020 to 2021 and remains below pre-COVID levels, signaling smaller cohorts for years to come.

covid_grades <- enr |>
  filter(is_state, subgroup == "total_enrollment",
         grade_level %in% c("K", "01", "06", "09"),
         end_year %in% 2019:2024) |>
  select(end_year, grade_level, n_students) |>
  tidyr::pivot_wider(names_from = grade_level, values_from = n_students)

stopifnot(nrow(covid_grades) > 0)
covid_grades
#> # A tibble: 6 x 5
#>   end_year     K  `01`  `06`  `09`
#>      <int> <dbl> <dbl> <dbl> <dbl>
#> 1     2019 42004 42941 46655 45383
#> 2     2020 42322 42987 47024 45430
#> 3     2021 36151 40342 44012 46115
#> 4     2022 37816 38583 42274 46429
#> 5     2023 37026 40181 41907 46727
#> 6     2024 35644 38406 41670 44871
Oregon kindergarten enrollment
Oregon kindergarten enrollment

(source)


3. Baker SD 5J more than doubled enrollment since 2010

Baker SD 5J grew from 2,056 to 4,829 students—a 135% increase—making it Oregon’s fastest-growing district by percentage.

baker <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         district_id == "1894") |>
  select(end_year, district_name, n_students)

stopifnot(nrow(baker) > 0)
baker
#>    end_year district_name n_students
#> 1      2010   Baker SD 5J       2056
#> 2      2011   Baker SD 5J       2056
#> 3      2012   Baker SD 5J       2089
#> 4      2013   Baker SD 5J       2074
#> 5      2014   Baker SD 5J       2164
#> 6      2015   Baker SD 5J       2398
#> 7      2016   Baker SD 5J       2620
#> 8      2017   Baker SD 5J       2944
#> 9      2018   Baker SD 5J       3329
#> 10     2019   Baker SD 5J       3832
#> 11     2020   Baker SD 5J       4089
#> 12     2021   Baker SD 5J       4669
#> 13     2022   Baker SD 5J       4527
#> 14     2023   Baker SD 5J       4453
#> 15     2024   Baker SD 5J       4829
Baker SD 5J enrollment growth
Baker SD 5J enrollment growth

(source)


Data Taxonomy

Category Years Function Details
Enrollment 2010-2024 fetch_enr() / fetch_enr_multi() State, district, school. Race (2016+)
Assessments Not yet available
Graduation Not yet available
Directory Current fetch_directory() Schools, districts, programs. Name, type, city
Per-Pupil Spending Not yet available
Accountability Not yet available
Chronic Absence Not yet available
EL Progress Not yet available
Special Ed Not yet available

See the full data category taxonomy

Quick Start

R

# install.packages("devtools")
devtools::install_github("almartin82/orschooldata")
library(orschooldata)
library(dplyr)

# Get 2024 enrollment data (2023-24 school year)
enr <- fetch_enr(2024)

# Statewide total
enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  pull(n_students)

# Top 10 districts
enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  arrange(desc(n_students)) |>
  select(district_name, n_students) |>
  head(10)

# Get multiple years
enr_multi <- fetch_enr_multi(2020:2024)

Python

import pyorschooldata as or_

# Get 2024 enrollment data (2023-24 school year)
enr = or_.fetch_enr(2024)

# Statewide total
state_total = enr[
    (enr['is_state']) &
    (enr['subgroup'] == 'total_enrollment') &
    (enr['grade_level'] == 'TOTAL')
]['n_students'].values[0]
print(state_total)

# Top 10 districts
top_districts = (
    enr[
        (enr['is_district']) &
        (enr['subgroup'] == 'total_enrollment') &
        (enr['grade_level'] == 'TOTAL')
    ]
    .sort_values('n_students', ascending=False)
    [['district_name', 'n_students']]
    .head(10)
)

# Get multiple years
enr_multi = or_.fetch_enr_multi([2020, 2021, 2022, 2023, 2024])

Explore More

Full analysis with 15 stories: - 15 Insights from Oregon School Enrollment Data — 15 stories - Getting Started with orschooldata - Function reference

Data Notes

Data Source

Oregon Department of Education Fall Membership Reports

Census Day

Fall Membership data is collected on the first school day in October (Census Day). This snapshot represents enrollment at a single point in time.

Available Years

Era Years Format Notes
Era 1 2010-2014 .xls Older Excel format
Era 2 2015-2024 .xlsx Modern format

15 years across ~210 districts and ~1,423 schools.

What’s Included

  • Levels: State, district, and campus
  • Grade levels: K, 01-12, TOTAL
  • Race/ethnicity: white, hispanic, asian, black, multiracial, native_american, pacific_islander (available 2016-2024)

What’s NOT Available

The Oregon Fall Membership Reports focus on enrollment counts: - Special populations (LEP, Special Ed, Economically Disadvantaged) - Gender breakdowns

For demographics beyond race/ethnicity, consult the Oregon Report Card system.

Suppression Rules

  • Values of * or <5 in the source data indicate suppressed small counts (typically fewer than 5 students)
  • These are converted to NA in the processed data
  • Suppression protects student privacy in small schools/programs

Deeper Dive


4. Portland Public Schools lost 4,700 students since 2019

Oregon’s largest district peaked at 48,677 students in 2019 and has declined every year since, dropping to 90% of its peak by 2024.

portland <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         district_id == "2180") |>
  select(end_year, district_name, n_students) |>
  mutate(pct_of_peak = round(n_students / max(n_students) * 100, 1))

stopifnot(nrow(portland) > 0)
portland
#>    end_year  district_name n_students pct_of_peak
#> 1      2010 Portland SD 1J      45678        93.8
#> 2      2011 Portland SD 1J      45678        93.8
#> 3      2012 Portland SD 1J      45718        93.9
#> 4      2013 Portland SD 1J      46190        94.9
#> 5      2014 Portland SD 1J      46549        95.6
#> 6      2015 Portland SD 1J      47647        97.9
#> 7      2016 Portland SD 1J      48383        99.4
#> 8      2017 Portland SD 1J      48198        99.0
#> 9      2018 Portland SD 1J      48650        99.9
#> 10     2019 Portland SD 1J      48677       100.0
#> 11     2020 Portland SD 1J      48559        99.8
#> 12     2021 Portland SD 1J      46924        96.4
#> 13     2022 Portland SD 1J      45123        92.7
#> 14     2023 Portland SD 1J      44681        91.8
#> 15     2024 Portland SD 1J      43979        90.3
Top Oregon districts
Top Oregon districts

(source)


5. High school grades are larger than elementary

Grade 9 enrollment exceeds kindergarten by several thousand students, reflecting the pandemic’s lasting impact on younger cohorts.

enr_2024 <- fetch_enr(2024, use_cache = TRUE)

grade_comparison <- enr_2024 |>
  filter(is_state, subgroup == "total_enrollment",
         grade_level %in% c("K", "01", "02", "03", "09", "10", "11", "12")) |>
  select(grade_level, n_students) |>
  arrange(grade_level)

stopifnot(nrow(grade_comparison) > 0)
grade_comparison
#>   grade_level n_students
#> 1          01      38406
#> 2          02      40577
#> 3          03      40026
#> 4          09      44871
#> 5          10      46733
#> 6          11      45424
#> 7          12      46162
#> 8           K      35644

6. 86 districts have fewer than 500 students

Rural Oregon is vast, and many small districts serve tiny populations spread across large geographic areas.

district_sizes <- enr_2024 |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  mutate(size_bucket = case_when(
    n_students < 500 ~ "Small (<500)",
    n_students < 2000 ~ "Medium (500-2K)",
    n_students < 10000 ~ "Large (2K-10K)",
    TRUE ~ "Very Large (10K+)"
  )) |>
  count(size_bucket)

stopifnot(nrow(district_sizes) > 0)
district_sizes
#>         size_bucket  n
#> 1    Large (2K-10K) 55
#> 2   Medium (500-2K) 59
#> 3      Small (<500) 86
#> 4 Very Large (10K+) 10
Oregon districts by size
Oregon districts by size

(source)


7. Oregon’s Hispanic student share rose from 22.5% to 25.8% in eight years

While total enrollment fell after 2020, Hispanic enrollment grew to 141,060 students—now more than one in four Oregon students.

hispanic_share <- enr |>
  filter(is_state, grade_level == "TOTAL",
         subgroup %in% c("total_enrollment", "hispanic")) |>
  select(end_year, subgroup, n_students) |>
  tidyr::pivot_wider(names_from = subgroup, values_from = n_students) |>
  filter(!is.na(hispanic)) |>
  mutate(hispanic_pct = round(hispanic / total_enrollment * 100, 1))

stopifnot(nrow(hispanic_share) > 0)
hispanic_share
#> # A tibble: 9 x 4
#>   end_year total_enrollment hispanic hispanic_pct
#>      <int>            <dbl>    <dbl>        <dbl>
#> 1     2016           576407   129410         22.5
#> 2     2017           578947   131089         22.6
#> 3     2018           580684   133822         23
#> 4     2019           581730   136186         23.4
#> 5     2020           582661   138273         23.7
#> 6     2021           560917   137101         24.4
#> 7     2022           553012   138112         25
#> 8     2023           552380   139928         25.3
#> 9     2024           547424   141060         25.8
Hispanic student share trend
Hispanic student share trend

(source)


8. Woodburn is 86% Hispanic—Oregon’s most concentrated district

Woodburn SD 103, south of Portland, has the highest Hispanic student share of any sizeable Oregon district at 86.1%.

hisp_districts <- enr_2024 |>
  filter(is_district, grade_level == "TOTAL",
         subgroup %in% c("total_enrollment", "hispanic")) |>
  select(district_name, subgroup, n_students) |>
  tidyr::pivot_wider(names_from = subgroup, values_from = n_students) |>
  mutate(hispanic_pct = round(hispanic / total_enrollment * 100, 1)) |>
  filter(total_enrollment >= 5000) |>
  arrange(desc(hispanic_pct))

stopifnot(nrow(hisp_districts) > 0)
hisp_districts
#> # A tibble: 27 x 4
#>    district_name          total_enrollment hispanic hispanic_pct
#>    <chr>                             <dbl>    <dbl>        <dbl>
#>  1 Woodburn SD 103                    5242     4514         86.1
#>  2 Hermiston SD 8                     5419     3256         60.1
#>  3 Forest Grove SD 15                 5809     3369         58
#>  4 Salem-Keizer SD 24J               38787    18050         46.5
#>  5 Reynolds SD 7                      9613     4229         44
#>  6 Hillsboro SD 1J                   18716     7725         41.3
#>  7 McMinnville SD 40                  6419     2436         37.9
#>  8 Gresham-Barlow SD 10J             11371     3768         33.1
#>  9 Centennial SD 28J                  5485     1755         32
#> 10 Tigard-Tualatin SD 23J            11620     3452         29.7
#> # i 17 more rows

9. Portland SD 1J is Oregon’s largest district at 43,979 students

Portland leads Salem-Keizer by over 5,000 students, though both have declined since their pre-COVID peaks.

largest <- enr_2024 |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL") |>
  arrange(desc(n_students)) |>
  select(district_name, n_students) |>
  head(10)

stopifnot(nrow(largest) > 0)
largest
#>                      district_name n_students
#> 1                   Portland SD 1J      43979
#> 2              Salem-Keizer SD 24J      38787
#> 3                 Beaverton SD 48J      37988
#> 4                  Hillsboro SD 1J      18716
#> 5  Bend-LaPine Administrative SD 1      17075
#> 6            North Clackamas SD 12      16874
#> 7                     Eugene SD 4J      16318
#> 8                  Medford SD 549C      13750
#> 9           Tigard-Tualatin SD 23J      11620
#> 10           Gresham-Barlow SD 10J      11371

10. White students dropped from 63.4% to 58.4% of Oregon enrollment since 2016

Oregon is diversifying rapidly. White enrollment fell by 46,000 students while Hispanic and multiracial populations grew.

race_trend <- enr |>
  filter(is_state, grade_level == "TOTAL",
         subgroup %in% c("white", "hispanic", "multiracial", "asian", "black")) |>
  select(end_year, subgroup, n_students) |>
  filter(!is.na(n_students))

stopifnot(nrow(race_trend) > 0)

race_wide <- race_trend |>
  tidyr::pivot_wider(names_from = subgroup, values_from = n_students)

race_wide
#> # A tibble: 9 x 6
#>   end_year asian black hispanic  white multiracial
#>      <int> <dbl> <dbl>    <dbl>  <dbl>       <dbl>
#> 1     2016 22726 13744   129410 365593       32597
#> 2     2017 23067 13654   131089 364581       34200
#> 3     2018 23324 13509   133822 362396       35677
#> 4     2019 23267 13301   136186 360197       37136
#> 5     2020 23208 13176   138273 358257       38306
#> 6     2021 22733 13021   137101 338528       38629
#> 7     2022 22145 12731   138112 329994       39219
#> 8     2023 22181 12982   139928 326100       40024
#> 9     2024 22288 13114   141060 319798       40294
Race/ethnicity enrollment trends
Race/ethnicity enrollment trends

(source)


11. 15 years of data reveal long-term shifts

Oregon’s enrollment data spans from 2010 to 2024, capturing the Great Recession recovery, pre-pandemic growth, COVID disruption, and early recovery.

decade_summary <- enr |>
  filter(is_state, subgroup == "total_enrollment", grade_level == "TOTAL",
         end_year %in% c(2010, 2015, 2020, 2021, 2024)) |>
  select(end_year, n_students) |>
  mutate(label = case_when(
    end_year == 2010 ~ "Post-recession",
    end_year == 2015 ~ "Mid-decade",
    end_year == 2020 ~ "Pre-COVID peak",
    end_year == 2021 ~ "COVID low",
    end_year == 2024 ~ "Current"
  ))

stopifnot(nrow(decade_summary) > 0)
decade_summary
#>   end_year n_students          label
#> 1     2010     561696 Post-recession
#> 2     2015     570857     Mid-decade
#> 3     2020     582661 Pre-COVID peak
#> 4     2021     560917      COVID low
#> 5     2024     547424        Current

12. Beaverton vs Hillsboro: Suburban rivals

Washington County’s two largest districts show different trajectories over the past decade.

wash_county <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         district_name %in% c("Beaverton SD 48J", "Hillsboro SD 1J")) |>
  select(end_year, district_name, n_students)

stopifnot(nrow(wash_county) > 0)

wash_county |>
  filter(end_year %in% c(2010, 2015, 2020, 2024))
#>   end_year    district_name n_students
#> 1     2010  Hillsboro SD 1J      20714
#> 2     2010 Beaverton SD 48J      37950
#> 3     2015  Hillsboro SD 1J      20884
#> 4     2015 Beaverton SD 48J      39763
#> 5     2020  Hillsboro SD 1J      20269
#> 6     2020 Beaverton SD 48J      41215
#> 7     2024  Hillsboro SD 1J      18716
#> 8     2024 Beaverton SD 48J      37988
Washington County suburban districts
Washington County suburban districts

(source)


13. Multiracial is Oregon’s fastest-growing racial group

Multiracial students grew from 32,597 in 2016 to 40,294 in 2024—a 23.6% increase—even as total enrollment declined.

multi <- enr |>
  filter(is_state, grade_level == "TOTAL", subgroup == "multiracial") |>
  select(end_year, n_students) |>
  mutate(growth_from_2016 = round((n_students / first(n_students) - 1) * 100, 1))

stopifnot(nrow(multi) > 0)
multi
#>   end_year n_students growth_from_2016
#> 1     2016      32597              0.0
#> 2     2017      34200              4.9
#> 3     2018      35677              9.4
#> 4     2019      37136             13.9
#> 5     2020      38306             17.5
#> 6     2021      38629             18.5
#> 7     2022      39219             20.3
#> 8     2023      40024             22.8
#> 9     2024      40294             23.6
Multiracial student growth
Multiracial student growth

(source)


14. Bend-LaPine grew 8% while Portland shrank

Bend-LaPine Administrative SD 1 added over 1,200 students since 2010, bucking statewide post-COVID decline trends.

bend <- enr |>
  filter(is_district, subgroup == "total_enrollment", grade_level == "TOTAL",
         district_id == "1976") |>
  select(end_year, district_name, n_students)

stopifnot(nrow(bend) > 0)
bend
#>    end_year                   district_name n_students
#> 1      2010 Bend-LaPine Administrative SD 1      15819
#> 2      2011 Bend-LaPine Administrative SD 1      15819
#> 3      2012 Bend-LaPine Administrative SD 1      16157
#> 4      2013 Bend-LaPine Administrative SD 1      16275
#> 5      2014 Bend-LaPine Administrative SD 1      16575
#> 6      2015 Bend-LaPine Administrative SD 1      17122
#> 7      2016 Bend-LaPine Administrative SD 1      17517
#> 8      2017 Bend-LaPine Administrative SD 1      17984
#> 9      2018 Bend-LaPine Administrative SD 1      18325
#> 10     2019 Bend-LaPine Administrative SD 1      18384
#> 11     2020 Bend-LaPine Administrative SD 1      18647
#> 12     2021 Bend-LaPine Administrative SD 1      17542
#> 13     2022 Bend-LaPine Administrative SD 1      17419
#> 14     2023 Bend-LaPine Administrative SD 1      17356
#> 15     2024 Bend-LaPine Administrative SD 1      17075
Bend-LaPine enrollment trend
Bend-LaPine enrollment trend

(source)


15. Grade-by-grade snapshot reveals demographic wave

Each grade level tells a story: today’s kindergartners are tomorrow’s high schoolers.

grade_snapshot <- enr |>
  filter(is_state, subgroup == "total_enrollment",
         grade_level %in% c("K", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"),
         end_year == 2024) |>
  select(grade_level, n_students) |>
  arrange(grade_level)

stopifnot(nrow(grade_snapshot) > 0)
grade_snapshot
#>    grade_level n_students
#> 1           01      38406
#> 2           02      40577
#> 3           03      40026
#> 4           04      41618
#> 5           05      41454
#> 6           06      41670
#> 7           07      42008
#> 8           08      42831
#> 9           09      44871
#> 10          10      46733
#> 11          11      45424
#> 12          12      46162
#> 13           K      35644
Grade-by-grade enrollment
Grade-by-grade enrollment

(source)