This document follows the budget of the Department of Education – Office of the Secretary (DepEd-OSEC) across ten fiscal years, from the FY 2018 enacted budget to the FY 2027 proposal, and traces each peso through the four stages of the public-expenditure cycle: proposed (NEP), enacted (GAA), released (allotment), committed (obligation), and finally paid out (disbursement).
It is the long-form companion to the DepEd-OSEC briefing deck. Where the deck compresses each point to a single slide, this version keeps the full reasoning and adds reference tables — most of them sortable and searchable — so that a reader can interrogate the figures directly rather than take the narrative on trust. Every table can be copied or exported to CSV from its toolbar.
The story has one organizing tension. DepEd-OSEC is, in budget terms, a payroll organization: roughly two-thirds to four-fifths of its money is teacher and staff salaries, and salaries are spent with near-perfect reliability. That makes the agency’s headline absorption look excellent. But it also means the headline number tells you almost nothing about the programs that actually deliver classrooms, textbooks, equipment, and subsidies — and those programs are where execution repeatedly breaks down. Most of what follows is an attempt to look past the salary block at the discretionary tail underneath it.
The FY 2027 proposal (NEP) is ₱914B for DepEd-OSEC — up about ₱41B (+5%) on the FY 2026 proposal and the largest yet, though it still sits ₱44B below the Congress-augmented 2026 enacted level (₱959B). The increase is concentrated in running schools: Operation of Schools — Elementary (+₱32B), Junior High (+₱18B), and Senior High (+₱9B), plus the teachers’ cash allowance (+₱7.5B). The student subsidies were reclassified, not cut: the Senior High Voucher (₱26.5B) and Educational Service Contracting (₱12.4B) are folded into a single new Government Assistance and Subsidies line (₱38.1B), roughly budget-neutral but harder to track by component. Several quality-and-access inputs are trimmed in the proposal — Computerization (−₱10.7B), New School Personnel Positions (−₱10.6B), Textbooks (−₱4.7B), and resilient-school infrastructure (−₱7.2B).
The DepEd-OSEC budget has grown about 1.7× in nominal terms, from a ₱552B enacted budget in 2018 to a proposed ₱959B in the 2026 GAA. Growth has been steady rather than smooth, with the steepest single-year jumps in 2023 and 2026.
In structure this is a teacher-salary organization. The three “Operation of Schools” lines — Elementary, Junior High, and Senior High — together account for 65–78% of the OSEC budget in every year, and Personnel Services alone is 64–80% of every year’s GAA. Operation of Schools – Elementary, by itself, is ₱358B in the 2026 GAA: more than a third of the entire office.
That structure is why headline absorption looks strong. Obligations run 93–97% of allotments and disbursements 86–92% — but this is carried almost entirely by Personnel Services, which disburses at 97–99% like clockwork. Strip the salaries away and a very different picture emerges.
The non-salary tail absorbs far worse. Textbooks and Other Instructional Materials disbursed just 2–17% of its allotment in every year on record; Basic Education Facilities, the agency’s capital-outlay bottleneck, has swung between 16% and 54% with no clear improvement. The GASTPE demand-side subsidies collapsed after 2022 — the Senior High School Voucher fell from near-full disbursement to 28% by 2025, and Educational Service Contracting from ~80% to the mid-30s.
Two structural shifts stand out at the top of the budget. Capital Outlay was squeezed from 22% of the budget in 2018 to 3–5% in 2021–2023, then restored sharply to about ₱100B (10%) in the 2026 GAA. And FY 2026 carries a record Congressional augmentation: the ₱873B NEP was raised to a ₱959B GAA, an ₱86B add-on after years in which the enacted budget barely departed from the Executive’s proposal.
The recurring policy question this raises: Congress channels its largest additions into exactly the procurement-heavy lines — facilities, textbooks, feeding — that already struggle most to disburse what they have. Capacity to spend, not willingness to appropriate, is the binding constraint.
Period. FY 2018 through FY 2027 for NEP and FY 2018 through FY 2026 for GAA — FY 2027 is the NEP (the Executive’s proposal) only, not yet debated or enacted and with no execution data, so wherever a chart or table shows FY 2027 the figure is proposed. Execution data — Adjusted Appropriations, Adjusted Allotments, Obligations, and Disbursements — is available for FY 2018–2025; FY 2026 reflects the proposed/enacted budget only, with no execution data yet.
Scope. The main analysis is DepEd Office of the Secretary only; the attached agencies (the National Museum, the ECCD Council, the National Book Development Board, and others) are summarised in a short attached-agencies section at the end. Figures are Current New Appropriations only — they exclude Continuing and Automatic Appropriations and Special Purpose Fund transfers. All amounts are in nominal pesos; no inflation adjustment is applied.
P/A/P consolidation. Two programs appear under two or three slightly different P/A/P labels across the years: the Educational Service Contracting (ESC) program and the Senior High School Voucher program. Each is reported here as a single continuous line so its trajectory can be read without artificial breaks.
Absorptive-capacity denominator. Unless stated otherwise, absorption ratios use Adjusted Allotments as the denominator — the closest available proxy for what the agency was actually cleared to spend in a given year.
Key terms. NEP (National Expenditure Program) is the Executive’s proposed budget; GAA (General Appropriations Act) is the enacted budget. Obligations are spending commitments (contracts signed, orders placed); Disbursements are cash actually paid out. The three ratios used throughout are O/A (Obligations ÷ Allotment), D/O (Disbursements ÷ Obligations), and D/A (Disbursements ÷ Allotment, the end-to-end measure).
evo <- totals_by_year %>%
filter(metric %in% c("NEP","GAA","AdjAllot","Obligations","Disbursements")) %>%
mutate(metric = factor(metric, levels = c("NEP","GAA","AdjAllot","Obligations","Disbursements"),
labels = c("NEP (proposed)","GAA (enacted)","Adj. Allotment",
"Obligations","Disbursements")))
ggplot(evo, aes(year, total, color = metric, group = metric)) +
geom_line(linewidth = 1.0) + geom_point(size = 2) +
scale_color_manual(values = exec_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = c(seq(2018, 2026, 2), 2027)) +
annotate("text", x = 2027, y = Inf, label = "proposed", vjust = 1.4, size = 3, color = "grey45") +
labs(title = "DepEd-OSEC budget, NEP through Disbursements (FY 2018–2027)",
subtitle = "The enacted budget tracks the proposal closely — until a record 2026 augmentation; the FY 2027 NEP proposes ~PHP 914B",
x = NULL, y = NULL,
caption = "FY 2027 is the NEP (proposed) only; FY 2026 reflects NEP/GAA only; execution runs through 2025.") +
theme_deped() + guides(color = guide_legend(nrow = 1))
Three features of this chart organize the rest of the document. First, the NEP and GAA lines sit almost on top of each other for eight of the nine years — DepEd is rarely a target of large Congressional revision — and then visibly separate in 2026. Second, the allotment, obligation, and disbursement lines track below the enacted budget in a stable band, and the disbursement line pulls away slightly in 2024–2025, hinting at a widening execution gap. Third, the overall slope is firmly upward: this is a growing budget in every multi-year stretch.
The table below gives the underlying figures for every year, in billions of pesos.
tbl_evo <- totals_by_year %>%
filter(metric %in% c("NEP","GAA","AdjAllot","Obligations","Disbursements")) %>%
mutate(value = total / 1e9) %>%
select(year, metric, value) %>%
pivot_wider(names_from = year, values_from = value) %>%
mutate(metric = factor(metric, levels = c("NEP","GAA","AdjAllot","Obligations","Disbursements"),
labels = c("NEP","GAA","Adj. Allotment","Obligations","Disbursements"))) %>%
arrange(metric) %>% rename(`PHP B` = metric)
kbl_clean(tbl_evo, font = 13, digits = 0, format.args = list(big.mark = ","), na = "")
| PHP B | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | 2027 |
|---|---|---|---|---|---|---|---|---|---|---|
| NEP | 585 | 498 | 518 | 568 | 589 | 666 | 712 | 746 | 873 | 914 |
| GAA | 553 | 500 | 520 | 556 | 591 | 676 | 715 | 734 | 959 | |
| Adj. Allotment | 477 | 530 | 517 | 607 | 642 | 720 | 769 | 802 | ||
| Obligations | 454 | 503 | 501 | 590 | 612 | 682 | 714 | 756 | ||
| Disbursements | 426 | 472 | 466 | 552 | 593 | 647 | 660 | 694 |
Reading the levels above as growth rates makes the budget’s rhythm clearer. The enacted budget actually contracted in 2019 (a post-election re-enactment year), then expanded every year after, with the two largest jumps being 2023 (+14%) and the 2026 proposal (+31% over the 2025 GAA, the bulk of it from the Congressional add-on).
growth <- totals_by_year %>%
filter(metric == "GAA") %>% arrange(year) %>%
mutate(`GAA (B)` = total/1e9,
`Δ vs prior yr (B)` = (total - lag(total))/1e9,
`Growth %` = (total/lag(total) - 1)) %>%
select(year, `GAA (B)`, `Δ vs prior yr (B)`, `Growth %`)
growth %>%
mutate(`GAA (B)` = round(`GAA (B)`,1),
`Δ vs prior yr (B)` = round(`Δ vs prior yr (B)`,1),
`Growth %` = scales::percent(`Growth %`, accuracy = 0.1)) %>%
kbl_clean(font = 13, align = "rrrr", na = "")
| year | GAA (B) | Δ vs prior yr (B) | Growth % |
|---|---|---|---|
| 2018 | 552.5 | ||
| 2019 | 500.3 | -52.3 | -9.5% |
| 2020 | 520.3 | 20.0 | 4.0% |
| 2021 | 556.4 | 36.1 | 6.9% |
| 2022 | 591.2 | 34.8 | 6.3% |
| 2023 | 676.1 | 85.0 | 14.4% |
| 2024 | 715.3 | 39.2 | 5.8% |
| 2025 | 734.2 | 18.9 | 2.6% |
| 2026 | 958.7 | 224.5 | 30.6% |
| 2027 |
Growth is measured on the enacted GAA. The 2026 figure compares the proposed/enacted 2026 budget to the 2025 GAA.
DepEd-OSEC’s budget is organized into seven PREXC programs. The chart shows how the enacted budget divides among them each year; the table that follows gives the exact peso amounts and each program’s share of the total.
comp <- df_long %>%
filter(metric == "GAA", year <= 2026, !is.na(amount)) %>%
group_by(year, category) %>%
summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(category = factor(category, levels = names(cat_pal)))
ggplot(comp, aes(year, amount, fill = category)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = cat_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "Composition of the GAA by PREXC program, 2018–2026",
subtitle = "Support to Schools and Learners is by far the largest program; Basic Education Inputs is second",
x = NULL, y = NULL) +
theme_deped() + guides(fill = guide_legend(nrow = 4, byrow = TRUE))
The Support to Schools and Learners Program — which houses the three Operation of Schools lines — dwarfs the others; it is the salary engine of the department. The Basic Education Inputs Program (textbooks, facilities, equipment, computerization) is a distant but important second, and it is here that most of the absorption problems documented later in this report live. The smaller programs — policy development, inclusive education, human-resource development — are modest in budget terms but not in mandate.
comp_tbl <- comp %>%
group_by(year) %>% mutate(share = amount/sum(amount)) %>% ungroup()
comp_amt <- comp_tbl %>%
mutate(amount = round(amount/1e9,1)) %>%
select(category, year, amount) %>%
pivot_wider(names_from = year, values_from = amount)
kbl_clean(comp_amt %>% rename(`Program (PHP B)` = category),
font = 12, digits = 1, format.args = list(big.mark=","), na = "") %>%
add_header_above(c(" " = 1, "General Appropriations Act, by year (PHP billions)" = ncol(comp_amt)-1))
| Program (PHP B) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| Basic Education Inputs Program | 169.1 | 77.7 | 62.8 | 40.2 | 45.2 | 66.5 | 92.2 | 87.5 | 174.7 |
| Education Human Resource Development Program | 3.4 | 2.0 | 2.0 | 1.9 | 1.9 | 2.1 | 4.1 | 2.8 | 5.1 |
| Education Policy Development Program | 7.2 | 7.9 | 7.9 | 7.9 | 8.2 | 13.8 | 13.9 | 12.6 | 16.0 |
| General Administration and Support | 26.2 | 13.9 | 8.1 | 14.4 | 14.7 | 21.8 | 22.1 | 19.9 | 29.2 |
| Inclusive Education Program | 1.3 | 1.2 | 1.2 | 17.5 | 16.3 | 5.4 | 6.0 | 6.1 | 6.8 |
| Support to Operations | 3.4 | 3.6 | 3.7 | 3.2 | 3.4 | 5.6 | 6.5 | 5.0 | 10.5 |
| Support to Schools and Learners Program | 342.0 | 393.9 | 434.6 | 471.2 | 501.5 | 560.9 | 570.4 | 600.3 | 716.4 |
Share of each year’s total budget for the same programs:
comp_pct <- comp_tbl %>%
mutate(share = round(share*100,1)) %>%
select(category, year, share) %>%
pivot_wider(names_from = year, values_from = share)
kbl_clean(comp_pct %>% rename(`Program (% of GAA)` = category),
font = 12, digits = 1, na = "")
| Program (% of GAA) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| Basic Education Inputs Program | 30.6 | 15.5 | 12.1 | 7.2 | 7.6 | 9.8 | 12.9 | 11.9 | 18.2 |
| Education Human Resource Development Program | 0.6 | 0.4 | 0.4 | 0.3 | 0.3 | 0.3 | 0.6 | 0.4 | 0.5 |
| Education Policy Development Program | 1.3 | 1.6 | 1.5 | 1.4 | 1.4 | 2.0 | 1.9 | 1.7 | 1.7 |
| General Administration and Support | 4.7 | 2.8 | 1.6 | 2.6 | 2.5 | 3.2 | 3.1 | 2.7 | 3.0 |
| Inclusive Education Program | 0.2 | 0.2 | 0.2 | 3.1 | 2.8 | 0.8 | 0.8 | 0.8 | 0.7 |
| Support to Operations | 0.6 | 0.7 | 0.7 | 0.6 | 0.6 | 0.8 | 0.9 | 0.7 | 1.1 |
| Support to Schools and Learners Program | 61.9 | 78.7 | 83.5 | 84.7 | 84.8 | 82.9 | 79.7 | 81.8 | 74.7 |
The same budget, cut a different way — by what the money buys rather than which program it sits in. Three expense classes matter for DepEd-OSEC: Personnel Services (PS, salaries and benefits), Maintenance and Other Operating Expenses (MOOE, the running costs of programs), and Capital Outlays (CO, infrastructure and equipment).
ec_levels <- c("Personnel Services (PS)","Maintenance & Other Op. Exp. (MOOE)","Capital Outlays (CO)")
comp_ec <- df_long_all %>%
filter(metric == "GAA", year <= 2026, expense_class %in% c("1PS","2MOOE","6CO")) %>%
group_by(year, expense_class) %>%
summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(expense_class = factor(expense_class, levels = c("1PS","2MOOE","6CO"), labels = ec_levels))
ggplot(comp_ec, aes(year, amount, fill = expense_class)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = ec_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "GAA composition by Expense Class, 2018–2026",
subtitle = "Personnel Services is 64–80% of the budget every year; Capital Outlays was squeezed, then restored in 2026",
x = NULL, y = NULL) +
theme_deped() + guides(fill = guide_legend(nrow = 1))
The PS block is the dominant feature and it grows roughly in line with the headcount of the school system. The Capital Outlay story is the most dynamic: CO was a substantial 22% of the 2018 budget, was compressed to the low single digits in 2021–2023 as fiscal space tightened during and after the pandemic, and is sharply restored in the 2026 GAA. The share table makes the swing explicit.
ec_share <- comp_ec %>%
group_by(year) %>% mutate(share = amount/sum(amount)) %>% ungroup()
ec_pct <- ec_share %>% mutate(share = round(share*100,1)) %>%
select(expense_class, year, share) %>%
pivot_wider(names_from = year, values_from = share)
kbl_clean(ec_pct %>% rename(`Expense class (% of GAA)` = expense_class),
font = 12.5, digits = 1, na = "")
| Expense class (% of GAA) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| Personnel Services (PS) | 63.9 | 74.8 | 74.1 | 78.7 | 80.0 | 75.8 | 73.2 | 74.1 | 68.0 |
| Maintenance & Other Op. Exp. (MOOE) | 13.9 | 16.4 | 18.3 | 17.8 | 16.6 | 19.0 | 20.1 | 21.3 | 21.6 |
| Capital Outlays (CO) | 22.2 | 8.8 | 7.6 | 3.5 | 3.4 | 5.2 | 6.7 | 4.6 | 10.4 |
That restoration is a setup for a question this report returns to repeatedly: Capital Outlay has historically been DepEd-OSEC’s weakest-absorbing expense class. Putting ₱100B of CO back into the budget only delivers classrooms if the agency can disburse it — and the recent record there is poor.
At the line-item level, concentration is extreme. The ten largest P/A/Ps in the FY 2027 proposal (NEP), charted below, account for the overwhelming majority of the office’s budget.
top10 <- pap_year %>%
filter(year == 2027, !is.na(NEP)) %>%
arrange(desc(NEP)) %>% slice_head(n = 10) %>%
mutate(pap = factor(pap, levels = rev(pap)))
ggplot(top10, aes(pap, NEP)) +
geom_col(fill = "#54278F", width = 0.75) +
geom_text(aes(label = php_b(NEP)), hjust = -0.1, size = 3.3, color = "grey20") +
coord_flip() +
scale_x_discrete(labels = function(x) str_wrap(x, 42)) +
scale_y_continuous(labels = php_b_axis, expand = expansion(mult = c(0, .20)), limits = c(0, NA)) +
labs(title = "Top 10 P/A/Ps by FY 2027 NEP (proposed)",
subtitle = "Operation of Schools – Elementary alone is PHP 390B — about 43% of the proposed OSEC budget",
x = NULL, y = NULL) +
theme_deped() +
theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))
The chart shows ten lines; the office has many more. The table below ranks every P/A/P by its FY 2027 proposal (NEP), alongside the FY 2026 proposal and enacted budget, so the full distribution — and the long tail of small programs — is available for inspection. Lines that existed only in one year (for example the reclassified subsidy lines) show a blank where they have no figure. Sort by any column, search by name, or export the whole thing.
all_paps <- pap_year %>% filter(year == 2027) %>%
transmute(`P/A/P` = pap, `NEP 2027 (B)` = NEP/1e9)
nep_gaa_26 <- pap_year %>% filter(year == 2026) %>%
transmute(`P/A/P` = pap, `NEP 2026 (B)` = NEP/1e9, `GAA 2026 (B)` = GAA/1e9)
all_paps <- all_paps %>% full_join(nep_gaa_26, by = "P/A/P") %>%
arrange(desc(`NEP 2027 (B)`))
dt_table(all_paps, page = 15,
money_cols = c("NEP 2027 (B)","NEP 2026 (B)","GAA 2026 (B)"))
Comparing the two proposals — the FY 2026 NEP against the FY 2027 NEP — isolates what the Executive itself chose to change, before Congress acts. The chart excludes the reclassified subsidy lines: in FY 2027 the Senior High Voucher (₱26.5B) and Educational Service Contracting (₱12.4B) are consolidated into a single “Government Assistance and Subsidies” line (₱38.1B) — a roughly budget-neutral relabelling, not a cut, that would otherwise swamp the chart with two large false “reductions” and one false “increase.”
excl_reclass <- c("GAS - Educational Service Contracting (ESC) for Private JHS",
"GAS - Senior High School Voucher Program",
"Government Assistance and Subsidies")
nep_change <- pap_year %>%
filter(year %in% c(2026, 2027), !pap %in% excl_reclass) %>%
select(pap, year, NEP) %>%
pivot_wider(names_from = year, values_from = NEP, names_prefix = "y") %>%
mutate(change = (y2027 - y2026) / 1e9) %>%
filter(!is.na(change), abs(change) >= 0.5)
ups <- nep_change %>% filter(change > 0) %>% arrange(desc(change)) %>% slice_head(n = 7)
downs <- nep_change %>% filter(change < 0) %>% arrange(change) %>% slice_head(n = 6)
nep_change <- bind_rows(ups, downs) %>% arrange(desc(change)) %>%
mutate(pap = factor(pap, levels = rev(pap)),
dir = ifelse(change >= 0, "Increased", "Reduced"))
ggplot(nep_change, aes(pap, change, fill = dir)) +
geom_col(width = 0.72) +
geom_text(aes(label = sprintf("%+.1f", change),
hjust = ifelse(change >= 0, -0.15, 1.15)),
size = 3, color = "grey25") +
coord_flip() +
scale_fill_manual(values = c("Increased" = "#1B7837", "Reduced" = "#D95F02")) +
scale_x_discrete(labels = function(x) str_wrap(x, 44)) +
scale_y_continuous(labels = function(v) paste0(peso, v, "B"),
expand = expansion(mult = c(0.16, 0.16))) +
labs(title = "What the Executive changed: FY 2026 NEP to FY 2027 NEP (PHP B)",
subtitle = "Proposal-to-proposal change, subsidy reclassification excluded",
x = NULL, y = NULL) +
theme_deped() +
theme(panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(color = "grey85"),
legend.position = "none")
The proposal leans into running schools: Operation of Schools — Elementary (+₱32B), Junior High (+₱18B), and Senior High (+₱9B), together with the teachers’ cash allowance (+₱7.5B), account for almost all of the net increase. The reductions fall on quality-and-access inputs — the Computerization Program (−₱10.7B), New School Personnel Positions (−₱10.6B, i.e. fewer new teacher items), resilient-school infrastructure (−₱7.2B), and Textbooks and other instructional materials (−₱4.7B). It is a proposal that funds operating existing schools more generously while trimming the equipment, construction, and new-hiring lines — a within-proposal tilt worth watching, since several of those trimmed lines are ones Congress has restored before.
Collapsing the budget to just the three school-operations lines against everything else shows how lopsided the distribution is.
oos <- c("Operation of Schools - Elementary (Kinder to Grade 6)",
"Operation of Schools - Junior High School (Grade 7 to Grade 10)",
"Operation of Schools - Senior High School (Grade 11 to Grade 12)")
share <- df_long %>%
filter(metric == "GAA", year <= 2026, !is.na(amount)) %>%
mutate(grp = case_when(
pap == oos[1] ~ "Operation of Schools - Elementary",
pap == oos[2] ~ "Operation of Schools - JHS",
pap == oos[3] ~ "Operation of Schools - SHS",
TRUE ~ "All other P/A/Ps")) %>%
group_by(year, grp) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(grp = factor(grp, levels = c("Operation of Schools - Elementary","Operation of Schools - JHS",
"Operation of Schools - SHS","All other P/A/Ps")))
school_pal <- c("Operation of Schools - Elementary" = "#08519C","Operation of Schools - JHS" = "#3182BD",
"Operation of Schools - SHS" = "#9ECAE1","All other P/A/Ps" = "#D9D9D9")
ggplot(share, aes(year, amount, fill = grp)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = school_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "Operation of Schools vs. everything else, FY 2018–2026 GAA",
subtitle = "The three school-level lines together are 65–78% of the OSEC budget",
x = NULL, y = NULL) +
theme_deped() + guides(fill = guide_legend(nrow = 2, byrow = TRUE))
Why this concentration matters, in four points:
DepEd is rarely heavily augmented. In most years the enacted GAA differs from the Executive’s NEP by under 2%. The chart below is therefore cumulative over all nine budget cycles, isolating where Congress has consistently added to — or trimmed from — the President’s proposal. Only movements of at least ₱0.5B are shown.
aug <- pap_year %>%
filter(year <= 2026) %>%
group_by(pap) %>%
summarise(nep = sum(NEP, na.rm = TRUE), gaa = sum(GAA, na.rm = TRUE), .groups = "drop") %>%
mutate(change = gaa - nep) %>% filter(abs(change) >= 5e8)
aug_plot <- bind_rows(
aug %>% arrange(desc(change)) %>% slice_head(n = 8),
aug %>% arrange(change) %>% slice_head(n = 8)) %>%
distinct() %>%
mutate(direction = ifelse(change >= 0, "Net increase (GAA > NEP)", "Net decrease (GAA < NEP)"),
hj = ifelse(change >= 0, -0.12, 1.12),
pap = factor(pap, levels = pap[order(change)]))
ggplot(aug_plot, aes(pap, change/1e9, fill = direction)) +
geom_col(width = 0.7) +
geom_text(aes(label = sprintf("%+.1fB", change/1e9), hjust = hj), size = 2.9, color = "grey20") +
coord_flip() +
scale_fill_manual(values = c("Net increase (GAA > NEP)" = "#1B9E77", "Net decrease (GAA < NEP)" = "#D95F02")) +
scale_x_discrete(labels = function(x) str_trunc(x, 44)) +
scale_y_continuous(labels = function(v) paste0(peso, v, "B"), expand = expansion(mult = c(0.20, 0.20))) +
labs(title = "Cumulative NEP-to-GAA change by P/A/P, 2018–2026",
subtitle = "Congress adds most to Basic Education Facilities; trims most from Computerization",
x = NULL, y = NULL) +
theme_deped() +
theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85")) +
guides(fill = guide_legend(nrow = 1))
The pattern carries a built-in tension. The lines Congress augments most — Basic Education Facilities, Textbooks, School-Based Feeding — are among the weakest absorbers in the entire portfolio (documented in the next section). Extra money is being routed, year after year, into precisely the programs least able to spend what they already have. Augmentation is an act of appropriation; it does nothing on its own to fix the downstream procurement and liquidation bottlenecks that keep these lines from disbursing.
The full cumulative table below lists every P/A/P with a material (≥₱0.5B) net change over the nine years, so the complete pattern of Congressional preference — not just the sixteen largest movements — is available.
aug_full <- aug %>%
transmute(`P/A/P` = pap,
`Σ NEP 2018–26 (B)` = nep/1e9,
`Σ GAA 2018–26 (B)` = gaa/1e9,
`Cumulative Δ (B)` = change/1e9) %>%
arrange(desc(`Cumulative Δ (B)`))
dt_table(aug_full, page = 10,
money_cols = c("Σ NEP 2018–26 (B)","Σ GAA 2018–26 (B)","Cumulative Δ (B)"))
At the whole-office level, DepEd-OSEC looks like a model absorber. All three execution ratios hold within a tight 86–97% band across 2018–2025.
absorp_long <- absorp_total %>%
select(year, oblig_allot, disb_oblig, disb_allot) %>%
pivot_longer(-year, names_to = "ratio", values_to = "value") %>%
mutate(ratio = factor(ratio, levels = c("oblig_allot","disb_oblig","disb_allot"),
labels = c("Obligations / Adj. Allotment","Disbursements / Obligations","Disbursements / Adj. Allotment")))
ggplot(absorp_long, aes(year, value, color = ratio, group = ratio)) +
geom_line(linewidth = 0.9) + geom_point(size = 2) +
scale_color_manual(values = absorp_pal) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.0), breaks = seq(0, 1, 0.2)) +
scale_x_continuous(breaks = 2018:2025) +
labs(title = "DepEd-OSEC absorptive capacity, 2018–2025",
subtitle = "At the aggregate, DepEd is a strong absorber — all three ratios hold in a tight 86–97% band",
x = NULL, y = NULL) +
theme_deped() + guides(color = guide_legend(nrow = 1))
absorp_total %>%
transmute(Year = year,
`Adj. Allotment (B)` = round(AdjAllot/1e9,1),
`Obligations (B)` = round(Obligations/1e9,1),
`Disbursements (B)` = round(Disbursements/1e9,1),
`O/A` = scales::percent(oblig_allot, accuracy = 1),
`D/O` = scales::percent(disb_oblig, accuracy = 1),
`D/A` = scales::percent(disb_allot, accuracy = 1)) %>%
kbl_clean(font = 13, align = "rrrrrrr", na = "")
| Year | Adj. Allotment (B) | Obligations (B) | Disbursements (B) | O/A | D/O | D/A |
|---|---|---|---|---|---|---|
| 2018 | 477.0 | 453.8 | 426.0 | 95% | 94% | 89% |
| 2019 | 529.9 | 503.3 | 472.2 | 95% | 94% | 89% |
| 2020 | 517.0 | 501.0 | 466.0 | 97% | 93% | 90% |
| 2021 | 607.5 | 590.0 | 552.2 | 97% | 94% | 91% |
| 2022 | 642.4 | 611.9 | 592.9 | 95% | 97% | 92% |
| 2023 | 719.9 | 682.3 | 647.4 | 95% | 95% | 90% |
| 2024 | 768.6 | 714.1 | 660.1 | 93% | 92% | 86% |
| 2025 | 802.0 | 755.7 | 693.9 | 94% | 92% | 87% |
The aggregate is a weighted blend, and decomposing it by expense class is where the headline number falls apart. The end-to-end disbursement-to-allotment ratio is plotted separately for each expense class below.
absorp_ec <- df_long_all %>%
filter(metric %in% c("AdjAllot","Disbursements"), expense_class %in% c("1PS","2MOOE","6CO"), year %in% 2018:2025) %>%
group_by(year, metric, expense_class) %>%
summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
pivot_wider(names_from = metric, values_from = amount) %>%
mutate(da = ifelse(AdjAllot > 0, Disbursements/AdjAllot, NA_real_),
expense_class = factor(expense_class, levels = c("1PS","2MOOE","6CO"), labels = ec_levels))
ggplot(absorp_ec, aes(year, da, color = expense_class, group = expense_class)) +
geom_line(linewidth = 0.9) + geom_point(size = 1.8) +
geom_text(aes(label = scales::percent(da, accuracy = 1)), vjust = -1.0, size = 2.9, show.legend = FALSE, color = "grey20") +
scale_color_manual(values = ec_pal) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.05), breaks = seq(0, 1, 0.2)) +
scale_x_continuous(breaks = 2018:2025) +
labs(title = "Disbursement-to-Allotment by Expense Class, 2018–2025",
subtitle = "Personnel Services absorbs at ~98%; MOOE is uneven; Capital Outlays swings wildly and mostly low",
x = NULL, y = NULL) +
theme_deped() + guides(color = guide_legend(nrow = 1))
absorp_ec %>%
mutate(da = round(da*100,0)) %>%
select(expense_class, year, da) %>%
pivot_wider(names_from = year, values_from = da) %>%
rename(`D/A by expense class (%)` = expense_class) %>%
kbl_clean(font = 12.5, na = "")
| D/A by expense class (%) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 |
|---|---|---|---|---|---|---|---|---|
| Personnel Services (PS) | 98 | 98 | 97 | 97 | 97 | 99 | 98 | 97 |
| Maintenance & Other Op. Exp. (MOOE) | 75 | 76 | 73 | 74 | 80 | 70 | 53 | 55 |
| Capital Outlays (CO) | 32 | 30 | 33 | 40 | 14 | 9 | 27 | 54 |
At the aggregate, DepEd-OSEC looks like a model absorber: disbursement-to-allotment holds at 86–92% every year, and taken alone that number suggests budget execution is not a problem. But that average is a weighted blend of a near-perfect Personnel Services block (98–99%) and a much weaker non-salary tail. MOOE disburses at 53–80% and has weakened sharply since 2023; Capital Outlay swings between roughly 9% and 54% and is low in most years. The programs that actually deliver classrooms, textbooks, equipment, and subsidies — the discretionary, procurement-heavy lines — are exactly where appropriated money piles up undisbursed. The headline figure is therefore misleading for service delivery: because salaries dominate, the agency-wide absorption rate hides the very execution failures that matter most for learners.
To make the paradox concrete, the next two tables rank P/A/Ps with a 2025 allotment of at least ₱1B by their end-to-end D/A ratio. The strongest absorbers are salary-driven school-operations lines and a handful of small, well-defined programs; the weakest are procurement- and subsidy-heavy.
abs_2025 <- pap_year %>%
filter(year == 2025, !is.na(AdjAllot), AdjAllot >= 1e9) %>%
mutate(`O/A` = Obligations/AdjAllot, `D/O` = Disbursements/Obligations,
`D/A` = Disbursements/AdjAllot, `Allotment (B)` = round(AdjAllot/1e9, 1))
Strongest absorbers, FY 2025 — disbursement at or near 100% is the norm where spending is payroll.
abs_2025 %>% arrange(desc(`D/A`)) %>% slice_head(n = 8) %>%
transmute(`P/A/P` = str_trunc(pap, 52), `Allotment (B)`,
`O/A` = scales::percent(`O/A`, accuracy = 1),
`D/O` = scales::percent(`D/O`, accuracy = 1),
`D/A` = scales::percent(`D/A`, accuracy = 1)) %>%
kbl_clean(font = 13, align = "lrrrr", na = "")
| P/A/P | Allotment (B) | O/A | D/O | D/A |
|---|---|---|---|---|
| Connectivity Enhancement Program for e-Learning i… | 1.5 | 100% | 100% | 100% |
| Operation of Schools - Junior High School (Grade … | 184.0 | 99% | 99% | 99% |
| Curriculum Programs, Learning Management Models, … | 6.8 | 100% | 99% | 99% |
| Operation of Schools - Elementary (Kinder to Grad… | 331.2 | 100% | 98% | 98% |
| Operation of Schools - Senior High School (Grade … | 58.9 | 99% | 99% | 98% |
| Policy and Research Program | 2.2 | 99% | 98% | 97% |
| Joint Delivery Voucher for Senior High School Tec… | 1.5 | 94% | 98% | 91% |
| Quick Response Fund | 2.6 | 99% | 92% | 91% |
Weakest absorbers, FY 2025 — instructional materials, equipment, facilities, and the demand-side voucher/ESC lines. Textbooks disbursed 14% of a ₱17B allotment.
abs_2025 %>% arrange(`D/A`) %>% slice_head(n = 8) %>%
transmute(`P/A/P` = str_trunc(pap, 52), `Allotment (B)`,
`O/A` = scales::percent(`O/A`, accuracy = 1),
`D/O` = scales::percent(`D/O`, accuracy = 1),
`D/A` = scales::percent(`D/A`, accuracy = 1)) %>%
kbl_clean(font = 13, align = "lrrrr", na = "")
| P/A/P | Allotment (B) | O/A | D/O | D/A |
|---|---|---|---|---|
| Learning Tools and Equipment | 4.4 | 49% | 21% | 10% |
| Textbooks and Other Instructional Materials | 17.2 | 58% | 24% | 14% |
| National Assessment Systems for Basic Education | 1.8 | 68% | 34% | 23% |
| Basic Education Facilities | 8.9 | 64% | 43% | 27% |
| GAS - Senior High School Voucher Program | 31.5 | 55% | 52% | 28% |
| GAS - Educational Service Contracting (ESC) for P… | 16.4 | 65% | 54% | 35% |
| Flexible Learning Options (ADM/ALS/EiE) | 5.9 | 86% | 41% | 35% |
| School-Based Feeding Program (SBFP) | 14.3 | 91% | 53% | 48% |
Both curated tables above are slices of the same underlying data. The interactive table below contains every P/A/P with a 2025 allotment, with all three ratios, sortable and searchable — the complete absorption picture rather than the top and bottom eight. Sort ascending on D/A to see the chronic problem lines; sort descending on Allotment to see where the largest sums sit.
abs_full <- pap_year %>%
filter(year == 2025, !is.na(AdjAllot), AdjAllot > 0) %>%
transmute(`P/A/P` = pap,
`Allotment (B)` = AdjAllot/1e9,
`Obligations (B)` = Obligations/1e9,
`Disbursements (B)` = Disbursements/1e9,
`O/A` = Obligations/AdjAllot,
`D/O` = ifelse(Obligations>0, Disbursements/Obligations, NA_real_),
`D/A` = Disbursements/AdjAllot) %>%
arrange(`D/A`)
dt_table(abs_full, page = 15,
money_cols = c("Allotment (B)","Obligations (B)","Disbursements (B)"),
pct_cols = c("O/A","D/O","D/A"))
Six of the most consequential programs are tracked below, each showing the enacted budget, the adjusted allotment, and disbursements together. Where the three lines sit on top of one another, execution is clean; where the disbursement line falls away from the allotment, money is being appropriated and released but not paid out.
trend_paps <- c(
"Operation of Schools - Elementary (Kinder to Grade 6)",
"Operation of Schools - Junior High School (Grade 7 to Grade 10)",
"Operation of Schools - Senior High School (Grade 11 to Grade 12)",
"Basic Education Facilities","New School Personnel Positions",
"GAS - Senior High School Voucher Program")
trend_dat <- pap_year %>% filter(pap %in% trend_paps) %>%
select(pap, year, GAA, AdjAllot, Disbursements) %>%
pivot_longer(c(GAA, AdjAllot, Disbursements), names_to = "metric", values_to = "amount") %>%
mutate(metric = factor(metric, levels = c("GAA","AdjAllot","Disbursements"),
labels = c("GAA (enacted)","Adj. Allotment","Disbursements")),
pap = factor(pap, levels = trend_paps,
labels = c("Op. of Schools - Elementary","Op. of Schools - JHS","Op. of Schools - SHS",
"Basic Education Facilities","New School Personnel Positions","SHS Voucher Program")))
trend_pal <- c("GAA (enacted)" = "#54278F","Adj. Allotment" = "#08519C","Disbursements" = "#31A354")
ggplot(trend_dat, aes(year, amount, color = metric, group = metric)) +
geom_line(linewidth = 0.9) + geom_point(size = 1.5) +
facet_wrap(~ pap, ncol = 3, scales = "free_y",
labeller = label_wrap_gen(width = 24)) + expand_limits(y = 0) +
scale_color_manual(values = trend_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(4)) +
scale_x_continuous(breaks = c(2018, 2022, 2026)) +
labs(title = "How the six largest programs have evolved (2018–2026)",
subtitle = "School-operations lines absorb cleanly; Facilities and the SHS Voucher show widening gaps",
x = NULL, y = NULL) +
theme_deped() + guides(color = guide_legend(nrow = 1))
The three school-operations panels are textbook clean execution — the disbursement line shadows the allotment. Basic Education Facilities and the SHS Voucher are the visible exceptions, with disbursements falling conspicuously short of what was released. Those two are the subjects of the next two sections.
GASTPE — Government Assistance to Students and Teachers in Private Education — is public money that follows students into private schools, through two channels: the Senior High School Voucher and Educational Service Contracting (ESC) for private junior high. For most of the period both disbursed well. Then both broke.
gastpe <- pap_year %>%
filter(pap %in% c("GAS - Senior High School Voucher Program","GAS - Educational Service Contracting (ESC) for Private JHS"),
year %in% 2018:2025, !is.na(AdjAllot), AdjAllot > 0) %>%
mutate(da = Disbursements/AdjAllot,
pap = factor(pap, levels = c("GAS - Senior High School Voucher Program","GAS - Educational Service Contracting (ESC) for Private JHS"),
labels = c("SHS Voucher Program","ESC (Educational Service Contracting)")))
ggplot(gastpe, aes(year, da, color = pap, group = pap)) +
geom_hline(yintercept = 1, linetype = "dotted", color = "grey60") +
geom_line(linewidth = 1.0) + geom_point(size = 2.2) +
geom_text(aes(label = scales::percent(da, accuracy = 1)), vjust = -1.0, size = 3.0, show.legend = FALSE, color = "grey20") +
scale_color_manual(values = c("SHS Voucher Program" = "#D95F02","ESC (Educational Service Contracting)" = "#7570B3")) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.1), breaks = seq(0, 1, 0.25)) +
scale_x_continuous(breaks = 2018:2025) +
labs(title = "Disbursement-to-Allotment: GASTPE demand-side subsidies",
subtitle = "Both programs disbursed at 80–100% through 2022, then collapsed",
x = NULL, y = NULL) +
theme_deped() + guides(color = guide_legend(nrow = 1))
For most of the period both lines disbursed well — the SHS Voucher ran 91–100% through 2018–2022. Then both collapsed: the Voucher fell to 76% in 2023, 53% in 2024, and 28% in 2025; ESC fell from around 80% to the mid-30s. Crucially, the allotments did not shrink — the money was appropriated and released, but not paid out. Whether the cause is a payment-processing or liquidation bottleneck, falling enrollment in the voucher program, or a deliberate slowdown, the data alone cannot say. What it can say is that the break is steep, recent, and concentrated in exactly the demand-side instruments meant to reach students outside the public system.
pap_year %>%
filter(pap %in% c("GAS - Senior High School Voucher Program","GAS - Educational Service Contracting (ESC) for Private JHS"),
year %in% 2018:2025) %>%
mutate(line = ifelse(str_detect(pap,"Voucher"),"SHS Voucher","ESC"),
da = ifelse(!is.na(AdjAllot)&AdjAllot>0, round(Disbursements/AdjAllot*100,0), NA_real_)) %>%
select(line, year, da) %>% pivot_wider(names_from = year, values_from = da) %>%
rename(`D/A (%)` = line) %>% kbl_clean(font = 13, na = "")
| D/A (%) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 |
|---|---|---|---|---|---|---|---|---|
| ESC | 87 | 93 | 66 | 79 | 82 | 72 | 34 | 35 |
| SHS Voucher | 91 | 93 | 96 | 97 | 100 | 76 | 53 | 28 |
Six procurement-heavy programs that have struggled to disburse for years are tracked below. The common thread is not the program area but the mechanism: every one of these depends on bidding, contracting, delivery, and liquidation rather than payroll.
low_paps <- c("Textbooks and Other Instructional Materials","Basic Education Facilities","Computerization Program",
"Learning Tools and Equipment","School-Based Feeding Program (SBFP)","National Assessment Systems for Basic Education")
low_dat <- pap_year %>% filter(pap %in% low_paps) %>%
mutate(da = ifelse(!is.na(AdjAllot) & AdjAllot > 0, Disbursements/AdjAllot, NA_real_),
pap = factor(pap, levels = low_paps,
labels = c("Textbooks & Instructional Materials","Basic Education Facilities","Computerization Program",
"Learning Tools and Equipment","School-Based Feeding Program","National Assessment Systems"))) %>%
select(pap, year, da) %>% tidyr::complete(year = 2018:2025, pap)
ggplot(low_dat, aes(year, da, group = 1)) +
geom_hline(yintercept = 1, linetype = "dotted", color = "grey60") +
geom_line(linewidth = 0.9, color = "#E6550D") + geom_point(size = 1.6, color = "#E6550D") +
geom_text(aes(label = scales::percent(da, accuracy = 1)), vjust = -0.9, size = 2.6, color = "grey20") +
facet_wrap(~ pap, ncol = 3, labeller = label_wrap_gen(width = 24)) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.15), breaks = seq(0, 1, 0.25)) +
scale_x_continuous(breaks = c(2018, 2021, 2024)) +
labs(title = "Disbursement-to-Allotment ratios: chronic under-absorbers (2018–2025)",
subtitle = "Textbooks has never crossed 20%; Basic Education Facilities is DepEd's infrastructure bottleneck",
x = NULL, y = NULL) +
theme_deped() + theme(legend.position = "none")
Textbooks and Other Instructional Materials is the standout failure: disbursement-to-allotment has stayed between 2% and 17% in every year on record — money for learning materials is appropriated and allotted, but barely paid out. Basic Education Facilities is the infrastructure bottleneck, the agency’s chronic capital-outlay problem, swinging between 16% and 54% with no clear improvement trend. The Computerization Program has been similarly weak (12–48%), with some recovery in 2024–2025, and the School-Based Feeding Program is volatile (35–87%) — a recurring annual program that nonetheless cannot disburse on a predictable schedule. The common thread is procurement, which is also where execution reform would have the most leverage.
low_dat %>% mutate(da = round(da*100,0)) %>%
pivot_wider(names_from = year, values_from = da) %>%
rename(`D/A (%)` = pap) %>% kbl_clean(font = 12.5, na = "")
| D/A (%) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | 2027 |
|---|---|---|---|---|---|---|---|---|---|---|
| Textbooks & Instructional Materials | 4 | 4 | 15 | 17 | 2 | 5 | 11 | 14 | ||
| Basic Education Facilities | 46 | 43 | 39 | 54 | 48 | 16 | 27 | 27 | ||
| Computerization Program | 13 | 27 | 28 | 23 | 17 | 12 | 42 | 48 | ||
| Learning Tools and Equipment | 4 | 7 | 0 | 1 | 5 | 20 | 23 | 10 | ||
| School-Based Feeding Program | 86 | 73 | 42 | 59 | 87 | 35 | 39 | 48 | ||
| National Assessment Systems | 39 | 14 | 5 | 10 | 26 | 21 | 19 | 23 |
The table below is the forward-looking reference for the office’s largest lines: for the top 30 P/A/Ps by the FY 2027 proposal (NEP), it gives the FY 2026 proposal and enacted budget and the most recent (2025) disbursement-to-allotment ratio, so budget levels sit beside how each line has recently absorbed. The full, unabridged P/A/P table is in the ranking section above; this one pairs budget levels with execution.
ref <- pap_year %>% filter(year == 2027, !is.na(NEP), NEP > 0) %>%
arrange(desc(NEP)) %>% slice_head(n = 30) %>%
transmute(pap, `NEP 2027 (B)` = NEP/1e9)
ctx <- pap_year %>% filter(year == 2026) %>%
transmute(pap, `NEP 2026 (B)` = NEP/1e9, `GAA 2026 (B)` = GAA/1e9)
da_25 <- pap_year %>% filter(year == 2025) %>%
transmute(pap, `D/A 2025` = ifelse(!is.na(AdjAllot) & AdjAllot > 0, Disbursements/AdjAllot, NA_real_))
ref %>% left_join(ctx, by = "pap") %>% left_join(da_25, by = "pap") %>%
rename(`P/A/P` = pap) %>%
dt_table(page = 15,
money_cols = c("NEP 2027 (B)","NEP 2026 (B)","GAA 2026 (B)"),
pct_cols = "D/A 2025")
2026 execution data is not yet available; the 2025 D/A column indicates how each line has most recently absorbed.
The main report covers the Office of the Secretary. DepEd also has a set of small attached agencies whose budgets are appropriated separately and are shown here on an appropriations basis only — no P/A/P-level execution data is published for them. They are a rounding error against the OSEC total (the largest, the National Museum, is proposed at ₱1.5B against OSEC’s ₱914B), but the FY 2027 proposal moves several of them sharply.
attached <- read_excel(file_path, sheet = "DepEd") %>%
filter(UACS_AGY_DSC != "Office of the Secretary") %>%
pivot_longer(matches("^(NEP|GAA)_\\d{4}_EXP_TOTAL$"), names_to = "var", values_to = "amount") %>%
separate(var, into = c("metric","year","tag","ec"), sep = "_") %>%
mutate(year = as.integer(year), amount = as.numeric(amount)) %>%
group_by(agency = UACS_AGY_DSC, year, metric) %>%
summarise(amount = if (all(is.na(amount))) NA_real_ else sum(amount, na.rm = TRUE), .groups = "drop")
att_2027 <- attached %>% filter(metric == "NEP", year == 2027, !is.na(amount), amount > 0) %>%
arrange(amount) %>% mutate(agency = factor(agency, levels = agency))
ggplot(att_2027, aes(agency, amount/1e6)) +
geom_col(fill = "#54278F", width = 0.72) +
geom_text(aes(label = paste0(peso, scales::comma(round(amount/1e6)), "M")),
hjust = -0.1, size = 3, color = "grey20") +
coord_flip() +
scale_x_discrete(labels = function(x) str_wrap(x, 34)) +
scale_y_continuous(labels = function(v) paste0(peso, scales::comma(v), "M"),
expand = expansion(mult = c(0, .24))) +
labs(title = "Attached agencies by FY 2027 NEP (proposed)",
subtitle = "Appropriations basis only; no execution data is published for these agencies",
x = NULL, y = NULL) +
theme_deped() +
theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))
att_tbl <- attached %>%
filter((metric == "NEP" & year %in% c(2026, 2027)) | (metric == "GAA" & year == 2026)) %>%
mutate(key = paste0(metric, year)) %>%
select(agency, key, amount) %>%
pivot_wider(names_from = key, values_from = amount) %>%
transmute(Agency = agency,
`NEP 2027 (M)` = NEP2027/1e6,
`NEP 2026 (M)` = NEP2026/1e6,
`GAA 2026 (M)` = GAA2026/1e6) %>%
arrange(desc(`NEP 2027 (M)`))
kbl_clean(att_tbl, font = 12.5, digits = 0, format.args = list(big.mark = ","), na = "")
| Agency | NEP 2027 (M) | NEP 2026 (M) | GAA 2026 (M) |
|---|---|---|---|
| National Museum of the Philippines | 1,531 | 812 | 987 |
| Teacher Education Council | 358 | 207 | 563 |
| National Academy of Sports | 254 | 246 | 541 |
| National Book Development Board | 165 | 152 | 202 |
| Philippine High School for the Arts | 131 | 157 | 218 |
| National Council for Children’s Television | 75 | 71 | 116 |
| Early Childhood Care and Development Council |
Two patterns stand out. The National Museum is proposed at ₱1.5B, nearly double its FY 2026 proposal — the single biggest mover. Several others (the Teacher Education Council, the National Academy of Sports, and the Philippine High School for the Arts) are proposed well below their FY 2026 enacted level, the familiar pattern of an Executive proposal that Congress has previously topped up. Because none of these agencies publishes P/A/P-level execution data, this appropriations-only view is as far as the absorption analysis can go for them.
Underlying data: DBM-published budget and execution data for the DepEd Office of the Secretary (Current New Appropriations only), FY 2018–2026. Execution measures (Allotments, Obligations, Disbursements) cover FY 2018–2025. Prepared as the long-form companion to the DepEd-OSEC budget briefing.