Seat Accessibility Model
What this answers: of India’s engineering and medical (MBBS + BDS) seat capacity, how much is actually reachable by what fraction of students — once you gate each seat twice: once on merit (exam percentile) and once on money (fee vs family budget). Those two gates are deliberately anti-correlated in the Indian seat design — cheap seats have high merit bars; low-merit seats are expensive — so “how many seats exist” is a wildly misleading measure of access. This model computes the honest one.
Built for a policy / advocacy paper. The findings write-up is in
paper.md; this README is how it’s built and how to reproduce it.
1. Worked example — one college, end to end
Section titled “1. Worked example — one college, end to end”Take a private-state MBBS college with 150 sanctioned seats. The model does this:
- Split into regulatory buckets (rules in
sources/assumptions.yaml → medical_split):pvt_govt_rate= 75 seats (50%) — the NMC-2022 rule: half of a private college’s seats are charged at the government rate, filled merit-first.management= 53 seats (35%) — FRC-capped but ₹10–25 L/yr.nri= 22 seats (15%) — ₹25–50 L/yr, effectively affluent-only.- Check enforced in code: 75 + 53 + 22 = 150 = total intake.
- Attach a fee band and a merit floor to each bucket (from the config):
pvt_govt_rate→ ~₹1.2 L/yr, merit floor ~90th percentile;management→ ~₹18 L/yr, floor ~50th (near qualifying);nri→ ~₹40 L/yr, floor ~qualifying. - A student reaches a bucket only if BOTH gates pass:
merit_percentile ≥ floorANDfundable_budget ≥ fee.- A 90th-percentile student from a ₹1 L/yr-budget family reaches the 75 cheap merit seats — but nothing else in this college.
- A 55th-percentile student from a ₹20 L/yr family reaches the 53 management seats (merit is a non-issue) but is locked out of the cheap ones (filled by higher scorers).
- A 75th-percentile student from a ₹1 L/yr family — the squeezed middle — reaches zero seats here: too low for the merit-gated cheap seats, too poor for the management seats.
- Aggregate this over every college and every student cell → the reachability heatmap and headline statistics.
That single college shows the whole point: 150 “available” seats, but for a high-merit poor student only 75 are reachable, and for the squeezed middle, none.
2. What the model produces
Section titled “2. What the model produces”| Output (on GCS) | What it is |
|---|---|
exploded_buckets.csv |
one row per (college × seat-bucket): seats, fee band, merit floor, domicile scope. The model’s core table. |
reachability.csv |
R[merit_band × budget_tier] = reachable seats, at every calibration (fee low/high × cutoff tight/loose × affordability conservative/generous). |
headline_stats.csv |
the paper’s punchline numbers per calibration. |
fig_heatmap.png |
reachable seats across merit percentile × budget tier. |
fig_access_curves.png |
cumulative reachable seats vs merit, one line per budget tier. |
fig_lorenz.png |
inequality-of-access curve (cumulative capacity vs cumulative students). |
fig_capacity_trend.png |
capacity by college founding year (medical) + AICTE govt-vs-private intake trend (engineering). |
bucket_summary.csv, fee_spotcheck.csv |
per-bucket table; Gujarat real-fee validation. |
3. Provenance map — where every number comes from
Section titled “3. Provenance map — where every number comes from”Pulled from BigQuery (avantifellows.external_data_sources):
nmc_fact_mbbs_seats— MBBS capacity: 780 colleges, 118,190 seats,management_category,year_of_inception. The MBBS split + trend anchor.nirf_fact_aggregate— engineering capacity:first_year_intakeper NIRF-ranked institute (latest academic_year per institute). This is the “where we have NIRF” engineering scope (~260 ranked institutes, ~252 k seats).aicte_fact_intake— engineering govt-vs-private intake trend, 2012–13→2022–23.plfs_fact_households— MPCE / household consumption distribution, used to ground the affordability budget-tier shares (weighted, calendar_2025).
Custom / built here (not in BQ):
- Bucket split — sanctioned intake exploded into regulatory buckets
(govt AIQ/state, private govt-rate/management/NRI, deemed management/NRI) via
the rules in
sources/assumptions.yaml. Encodes NMC-2022 (50% govt-rate), the 15% AIQ, and the deemed “no-government-quota” reality. - Two-gate reachability — the merit×money computation in
build_model.py. - Management → archetype normalisation — NMC has no “Deemed” label
(Government/Trust/Society/Private only); engineering archetype derived from
College DB
college_type.
Non-BQ inputs — fetched from GCS (College DB origin):
bds_all_colleges_2025-26.csv— BDS capacity (330 colleges; BQ has no BDS seat matrix). From Avanti’s College DB medical-national-ranks pipeline.college_master.csv— engineering management archetype vianirf_idjoin.gujarat_acpc_2024.csv— real per-course fees, used only to spot-check the indicative fee bands (Gujarat).
All modelling choices live in ONE file: sources/assumptions.yaml
— split shares, fee bands, merit floors, budget tiers, qualifier counts. To
change an assumption you edit that file and rerun; you never touch the code.
4. Reproduce it
Section titled “4. Reproduce it”# 1. fetch the non-BQ inputs into sources/ (BQ + these = full reproduction)gcloud storage cp \ "gs://avantifellows-external-data/seat-accessibility/inputs/*" \ analysis/neet-inequity-paper/sources/
# 2. build the model (reads BQ + sources/, writes output/)python3 build_model.py
# 3. render figures + tablespython3 analyze.pyRequires bq authenticated (see repo docs/BQ_SETUP.md) and pandas,
matplotlib, pyyaml.
5. Where the estimate is soft (read before citing a number)
Section titled “5. Where the estimate is soft (read before citing a number)”- Fees are indicative, not sourced per-college. No systematic Indian fee dataset exists. Bands come from published FRC caps / university notifications and are swept low/high to bracket. Gujarat ACPC real fees validate the accessible end (merit medical ~₹96 k/yr, engg ~₹75 k/yr — both inside the bands); management/NRI fees can’t be validated this way.
- Management “cutoffs” are demand-clearing prices, not fixed floors — swept tight/loose.
- Affordability is a modelling assumption. PLFS gives the consumption distribution (≈0.1 % of households consume ≥₹10 L/yr); fundable outlay lifts that with loans + an aspirant-skew factor. Reported at two calibrations. This input drives the answer as much as the seat data — never quote a single point.
- Deemed medical colleges are not separately identified. NMC labels them Trust/Society/Private, so they get the private-state 50%-govt-rate bucket. If genuine deemed universities (Manipal, DY Patil, …) don’t honour that rule, the true government-rate share is lower than 40.8 % (nearer ~30 %) and the affluent-only share higher. Directional caveat; a deemed-identification join is future work.
- Engineering scope = NIRF-ranked only. Undercounts the private long tail (AICTE shows ~1 M private engg seats vs the ~250 k modelled here) — so the engineering affluent-only share is understated.
- Domicile: state-quota buckets carry
scope=state; areachable_seats_nationalcolumn isolates what an out-of-state student can reach. Full state-by-state fragmentation is not modelled in v1. - Trend caveat: medical trend attributes current seat counts to each college’s founding year (survivorship + current-size proxy), not historical seat counts.
6. Replication data
Section titled “6. Replication data”De-identified model outputs (college-level aggregates, no PII) on GCS:
- exploded_buckets.csv
- reachability.csv
- headline_stats.csv
- Figures + tables:
gs://avantifellows-bq-assistant/seat-accessibility/ - Inputs:
gs://avantifellows-external-data/seat-accessibility/inputs/