← Back to the Compare tab

Technical Notes: Compare

How the Compare tab’s data were prepared, written for analysts. For a plain-language introduction, see the Guide.

The Compare tab draws two figures from the FLANA 2025 survey (Foundational Literacy and Numeracy Assessment, Usawa Agenda): a figure builder (pick an indicator and a comparison) and an x-vs-y scatter. This page sets out the sources, sample sizes, weighting, recoding, suppression rule and validation behind them.

Sources

The figure builder uses two microdata extracts, supplied as Stata files with a variable codebook:

  • 2025 FLANA household_data_dashboard.dta — one row per child from the household survey: assessment outcomes, child and household characteristics, survey weight.
  • 2025 FLANA Primary_school data_dashboard.dta — one row per surveyed primary school: staffing, enrolment, WASH and infrastructure variables, school survey weight.

One R script (scripts/generate_tab2_data.R) reads both files and pre-computes the entire universe of possible figures — every valid indicator × comparison (× optional second comparison) table, survey-weighted, with suppression resolved per cell — as JSON (205 household tables, 144 school tables, and 96 Junior School tables). The browser looks up and draws the selected table; it computes no statistics. Every one-axis table carries a trailing National (household) or Average (school) reference row computed on the full dataset, not the union of the displayed categories — it includes, for example, the four gender-“Other” children and the 46 refugee schools that carry no residence value.

The scatter uses a separate pipeline (scripts/generate_compare_data.R) and different source files — see the scatter below.

Sample sizes

  • Household dataset: 76,219 sampled children, of whom 43,915–45,118 (depending on the subject) carry an English or Mathematics assessment outcome; the rest are outside the assessed age range or were not assessed. Explore’s Household count is smaller, 22,213 children assessed, because Explore shows Usawa’s delivered tables for Grades 3, 4 and 6 only; see Technical Notes: Explore, Sample sizes.
  • Junior School dataset: 17,758 sampled children in Grades 7, 8 and 9 (6,707, 5,462 and 5,589), a slice of the same household file, with the three proficiency outcomes only (15,894 children carry a result). Grades 7 and 9 were added in November 2026 and Grade 8 on 10 November; its National row covers all three grades. It compares by region, county, gender, wealth, location and grade. The microdata records school type only for Grades 1 to 6, so there is no public–private split for these grades.
  • Grade is a comparison for the household proficiency outcomes (Grades 3, 4 and 6, the grades Explore reports). Children in other grades fall outside its categories, but the National row still covers every child with a result, as a footnote under the figure says.
  • School dataset: 1,527 sampled primary schools — 1,372 public, 109 private, 46 refugee community schools.
  • Compare and Explore differ slightly on schools. Explore leaves the 46 refugee community schools out (1,481 schools); Compare keeps them so it can split by refugee status. A Compare average can therefore differ a little from Explore’s: the learner–teacher ratio is 41.9 here and 41.8 on Explore, and North Eastern 48.9 against 47.6. A footnote under every school figure says so.
  • The footer counts the records Compare’s tables are built on (76,219 children; 1,527 schools), not Explore’s.

Weighting

Builder estimates are survey-weighted, matching the FLANA report’s methodology:

  • Child-level estimates use the household file’s Weight column.
  • School-level estimates use the school file’s school_weight column.
  • Three school indicators are pooled weighted ratios rather than school-weighted means, so larger schools count for more: teacher absenteeism (absent ÷ employed teachers), teachers trained in-service (trained ÷ all primary teachers, the Explore tab’s definition, added November 2026) and the teacher gender split. Absenteeism and the in-service share exclude the two schools with no teachers (n = 1,525).
  • Schools with at least one working computer is a weighted share of schools: a school counts as yes when it reports at least one computer for learners (s115h above 0). It covers the 971 schools that report a computer count; the other 556 left the question blank and are excluded. It replaced computers per 100 learners (a pooled ratio) in October 2026 and uses the same definition as the Explore tab’s indicator.

The scatter is the exception: its school-level source carries no weights, so its bins and fitted lines are unweighted (see below).

Recoding and cleaning

All recoding happens once, in the pipeline script:

  • Mother’s education is collapsed into five bands: None / adult literacy, Primary, Secondary, Post-secondary cert., Degree +. Household head’s education uses the same bands (bottom band None only — the head’s codes carry no adult-literacy category). The exact code-to-band mapping: dropout codes fold into the level dropped out of (Primary school dropout → Primary, Secondary school dropout → Secondary); Post-primary Certificate also folds into Secondary; Diploma and Post-secondary Certificate together form Post-secondary cert.; None and Adult literacy school form the bottom band.

  • School-type labels carry trailing whitespace in the source file and are trimmed before use.

  • The LCP (low-cost private schools) category has zero observations in the school file and is dropped; the pipeline fails loudly if that ever changes.

  • Mother’s age uses 999 as a missing-value sentinel; values above 120 are set to missing.

  • Teacher absenteeism: 60 schools report more teachers present than employed; the absent count is clamped at zero.

  • Child gender takes the values Boys and Girls; four children recorded as “Other” are too few to report and are excluded from gender comparisons.

  • Verbose codebook labels (income source, homework assistance, home language) are shortened by dropping their parenthetical or “, specify” qualifiers, and American spellings carried by the instrument’s own labels are adjusted to British English — “Casual labor” is shown as “Casual labour”. The source data is unchanged; the adjustment is applied to display labels only.

  • Household head’s main income source is collapsed from the codebook’s eleven sources into five groups:

    Codebook source Shown as
    Farming Farming
    Casual labour Casual labour
    Self-employment Self-employment
    Formal employment – public sector; Formal employment – private sector Formal employment
    Remittances; Pension or retirement benefits; Government assistance; Rental income; No regular income; Other Transfers and other

    The pipeline stops if the codebook ever carries a source the mapping does not name.

  • County performance bands rank the 47 counties on weighted combined English-and-Mathematics proficiency — the weighted percentage meeting both thresholds (the delivered combined variable), not the mean of the separate English and Mathematics percentages — and cut the ranking into quintiles: rank ntiles over the 47 counties ranked ascending (ties broken by county name), with the larger groups first (10, 10, 9, 9, 9).

Suppression rule

Household cells with fewer than 50 unweighted observations are suppressed: the cell keeps its sample size but loses its value, and the figure labels it “insufficient sample”. This guards against unstable estimates from thin cross-tabulations.

A group with no observations at all is labelled “no data” instead, in both universes, and is never drawn as a zero-length bar: for example, refugee-community schools exist in only some regions, so a region × refugee status figure shows “no data” beside the other regions’ refugee bars.

The school universe is not suppressed, by design: it is a designed sample of 1,527 schools whose strata are legitimately small (refugee 46, Nairobi 33); an n < 50 rule would erase comparisons the tab exists to show.

Validation against the FLANA 2025 report

A set of the report’s published results was recomputed from the microdata by a scripted check and compared with the pipeline outputs:

  • The microdata reproduces the report. English proficiency by gender, location and schooling status lands within 0.7 percentage points of the published figures; the Grade-3 cells within 1.0 point. The residual differences are inherent to the delivered extract, not the pipeline (which matches a direct microdata recomputation to 0.01 pp).
  • Two known discrepancies, each with a build consequence:
    1. Out-of-school assessment results differ from the report by 9–18 points — the extract holds only about 200 assessed out-of-school children. The dashboard therefore never splits assessment results by schooling status.
    2. Weighted absolute counts in the report use a different, county-varying weight scaling than the extract’s weight column. The dashboard therefore shows percentages (and weighted means for school-file ratios) only, never absolute counts.

The scatter

The scatter plots any two indicators against each other, per dataset. In every universe the axes hug the plotted dots (about 5% padding, never forced to zero), with the fitted line and band clipped to that range.

Sources. A dedicated script (scripts/generate_compare_data.R) builds data/processed/compare.json from:

  • 13_april_final_schools.csv — school-level records from the April delivery of the FLANA 2025 survey: 1,481 schools, one row per school, 25 delivered indicators — including three absent from the later aggregate delivery (operational computer labs, teenage pregnancy rate, return-to-school rate after pregnancy). Four of the delivered indicators are excluded pending corrected source data: the shares of schools connected to the internet and with an operational computer lab were delivered as zero for every school, and the teenage pregnancy and return-to-school rates carry implausible values (far above their possible maxima). The three learner attendance rows are also not shown, as on the Explore tab (absenteeism carries the same information). The scatter therefore offers the remaining 18 school indicators.
  • Household 2025/tab 1.csv and tab 2.csv — the county-level proficiency tables the Explore tab uses: 47 counties, one row per county, 120 proficiency metrics (3 proficiency measures × 10 views × 4 grades, including the derived “Grades 3, 4 and 6 combined”).
  • 2025 FLANA household_data_dashboard.dta — the household microdata (the same file the figure builder uses), from which seven county covariates are computed (see below), bringing the county scatter to 127 metrics in all.
  • Junior School — a third, county-level universe from the same household microdata: 63 learning outcomes for Grades 7, 8 and 9 (3 proficiency measures × 7 views × 3 grades, by the method the Explore tab uses) plus the seven county covariates, 70 metrics in all. It opens on mothers’ education against Grade 7 literacy.

Schools with at least one working computer is not offered in the scatter: it is derived from the school microdata, which has no school identifier to match its schools to the April records.

School universe — binned. 1,481 raw dots overplot, so the pipeline pre-computes, for every ordered pair of indicators: up to 20 equal-count bins of the x variable (never fewer than 5 schools per bin) over the schools carrying both variables, each bin drawn at its mean x and mean y with dot area showing its school count; and an OLS line with a classical 95% confidence band, fitted on all the individual schools, not the bins. The browser only evaluates the stored coefficients at the axis ends and clips the stored band to the dot range, interpolating between its grid points at the edges — display geometry, not statistics. Pairs whose x variable takes a single value ship no line and render dots only. The school file carries no survey weights, so these bins and fits are unweighted.

Household and Junior School universes — raw dots. Each of the 47 dots is a nameable county; binning them would destroy information, so they render as delivered (values survey-weighted, upstream by the Usawa Agenda data team or, for the derived measures and the Junior School outcomes, by the pipeline). The trend line with its 95% band is fitted in the browser on the 47 county points — the one statistical computation the site runs client-side. A caveat appears below the chart when fewer than 30 units carry both variables.

Log scale (county universes). Some county covariates are skewed: children out of school has a median of 2.3% across counties, but eight counties in the arid north lie between 10% and 26%, so on a linear axis the other counties crowd together at the bottom. A Log scale tick box under the Household and Junior School selectors puts each axis on a log scale, so every gridline step multiplies the value and the low cluster spreads out, with all 47 counties kept. An axis with a value at or below zero (some gap views) stays linear, and a footnote says so. With the box ticked, the trend line and band are fitted on the log values. The school scatter has no log option, because its line is pre-computed on the linear scale.

County covariates. Seven county-level covariates are computed directly from the household microdata and offered as scatter axes alongside the proficiency measures: the share of children whose household head has secondary education or higher, the same for the mother, the share living in urban areas, the share in the rich wealth tercile, and the share who attended pre-primary before Grade 1. Two more, learners in private schools and children out of school (aged 6 to 17), are the Explore tab’s derived indicators, computed by the same shared script (scripts/lib/derived_indicators.R), so their county values are identical on both tabs. Education uses the figure builder’s five ordered bands, with the top three — Secondary (including secondary-school dropouts and post-primary certificates), Post-secondary cert. and Degree + — counting as “secondary or higher”. Each covariate is a survey-weighted (Weight) share over the children with a non-missing value for that variable; children missing it are excluded from that covariate’s denominator. The standard household rule would suppress any county with fewer than 50 unweighted observations for a variable; no county falls below it. These are descriptive covariates, not causal estimates.

Differences from the Explore tab’s preparation. Teachers per classroom is shown as the raw teachers ÷ classrooms ratio on both tabs, higher is better. No suppression applies: school points are individual survey observations and county points are large-sample aggregates.

Indicator catalogue

Generated from the Compare data (tab2/*.json) every time it is rebuilt, so it always matches the “Show me” dropdown. All estimates are survey-weighted (see Weighting); a pooled ratio divides weighted totals rather than averaging per-school ratios, so larger schools count for more.

Household

Indicator Definition Unit Numerator Denominator Source column Direction Standard
Meets minimum proficiency in literacy Survey-weighted share of children for whom english_meet_comprehension is yes. % children answering yes children with an answer english_meet_comprehension Higher is better none
Meets minimum proficiency in numeracy Survey-weighted share of children for whom math_meet_divide is yes. % children answering yes children with an answer math_meet_divide Higher is better none
Meets minimum proficiency in both literacy and numeracy Survey-weighted share of children for whom both_meet_divdecomprehension is yes. % children answering yes children with an answer both_meet_divdecomprehension Higher is better none
Proficiency: literacy, numeracy and both Survey-weighted shares meeting the minimum proficiency level in Literacy, Numeracy, Both. % — — english_meet_comprehension, math_meet_divide, both_meet_divdecomprehension Higher is better none
Schooling status Survey-weighted share of children in each category of schooling_status: In school, Never Enrolled, Dropout. % — — schooling_status No direction none
Attended pre-primary before Grade 1 Survey-weighted share of children for whom prior_preprimary_attendance is yes. % children answering yes children with an answer prior_preprimary_attendance Higher is better none
Mother’s highest education level Survey-weighted share of children in each category of mother_edu_band: None / adult literacy, Primary, Secondary, Post-secondary cert., Degree +. % — — mother_edu_band No direction none
Household head’s highest education level Survey-weighted share of children in each category of head_edu_band: None / adult literacy, Primary, Secondary, Post-secondary cert., Degree +. % — — head_edu_band No direction none
Main language spoken at home Survey-weighted share of children in each category of home_language: English, Kiswahili, Mother tongue, Other. % — — home_language No direction none
Household head’s main income source Survey-weighted share of children in each category of income_source: Farming, Casual labour, Self-employment, Formal employment, Transfers and other. % — — income_source No direction none
Who assists the child with homework Survey-weighted share of children in each category of homework_assist_lab: Mother, Father, Both mother and father, Other family Member, None. % — — homework_assist_lab No direction none

Junior School

Indicator Definition Unit Numerator Denominator Source column Direction Standard
Meets minimum proficiency in literacy Survey-weighted share of children for whom english_meet_comprehension is yes. % children answering yes children with an answer english_meet_comprehension Higher is better none
Meets minimum proficiency in numeracy Survey-weighted share of children for whom math_meet_divide is yes. % children answering yes children with an answer math_meet_divide Higher is better none
Meets minimum proficiency in both literacy and numeracy Survey-weighted share of children for whom both_meet_divdecomprehension is yes. % children answering yes children with an answer both_meet_divdecomprehension Higher is better none
Proficiency: literacy, numeracy and both Survey-weighted shares meeting the minimum proficiency level in Literacy, Numeracy, Both. % — — english_meet_comprehension, math_meet_divide, both_meet_divdecomprehension Higher is better none

Primary School

Indicator Definition Unit Numerator Denominator Source column Direction Standard
Learner–teacher ratio Survey-weighted mean of primary_learner_teacher_ratio across schools. learners per teacher — — primary_learner_teacher_ratio Lower is better none
Teacher gender split Female and male shares of teachers, from survey-weighted teacher counts. % — — teacher counts by sex No direction none
Teacher absenteeism on visit day Survey-weighted pooled ratio: total teachers_absent ÷ total teachers_total × 100. % teachers_absent teachers_total teachers_absent, teachers_total Lower is better none
Average class size Survey-weighted mean of class_size across schools. learners per class — — class_size Lower is better none
Boys per functional toilet Survey-weighted mean of fuctional_toilets_ratio_boys across schools. boys per toilet — — fuctional_toilets_ratio_boys Lower is better none
Girls per functional toilet Survey-weighted mean of fuctional_toilets_ratio_girls across schools. girls per toilet — — fuctional_toilets_ratio_girls Lower is better none
Learners per hand-washing point Survey-weighted mean of fuctional_handw_ratio_learners across schools. learners per point — — fuctional_handw_ratio_learners Lower is better none
Schools connected to the internet Survey-weighted share of schools for whom has_internet is yes. % schools answering yes schools with an answer has_internet Higher is better none
Schools with at least one working computer Share of schools reporting at least one computer for learners (s115h above 0), among schools that report a count. % schools answering yes schools with an answer s115h Higher is better none
Teachers trained in-service Share of primary school teachers who have had in-service training: all trained teachers divided by all teachers, survey-weighted. % teacher_trained_int total_primary_teachers teacher_trained_int, total_primary_teachers Higher is better none
Trained guidance and counselling teachers per school Number of teachers trained in guidance and counselling, averaged per school. teachers per school — — s119b Higher is better none

Discretionary choices

Choice Rationale
All builder estimates survey-weighted (Weight household, school_weight school). Matches the FLANA report, so dashboard and report figures are comparable.
Household cells below n = 50 unweighted are suppressed and labelled “insufficient sample”. Thin cells produce unstable estimates.
The school universe is not suppressed. Its strata are legitimately small (refugee 46, Nairobi 33); an n < 50 rule would erase the comparisons the tab exists to show.
The full table universe is pre-computed to JSON; the county scatter’s trend line is the only statistic computed in the browser. Keeps the page instant and every displayed number inside one audited pipeline; 47 county aggregates are the deliberate carve-out.
School scatter lines are fitted on individual schools, not the displayed bins; household scatter lines are fitted on the displayed county aggregates. Preserves the intended unit of analysis for each dataset.
The school scatter renders equal-count bins; the county scatter renders raw dots. 1,481 dots overplot, and the fit still uses every school; 47 dots are each a nameable county.
Figure styling follows the conventions of the published report figures (Usawa palette, horizontal bars, white in-bar labels on stacked figures, “Percent” axis, whole numbers), ported to OJS/Plot. Keeps dashboard figures consistent with the published report figures; pixel identity with ggplot is not required.
Single-series bars are shaded in the Explore page’s purple hue, in five steps by rank among the bars shown: darkest is best, inverted where lower is better. There is no red, because the figure builder compares groups, not counties against a standard. National/Average is a dashed reference line. Split figures draw one dashed rule at the overall national average instead of a bar set; bundled-series figures (the joint proficiency view) draw one rule per series in the series colour, as each series is a distinct indicator. Matches the colour language of the Explore page, where purple means better, and encodes performance; the reference stays visible under a split without per-category clutter.
Where the grouping has no natural order (region, county, school type), bars rank worst → best bottom to top; ordered groupings keep their natural order. Ranking helps the eye where categories carry no order and a “best” is unambiguous.
Ordered category sets use a navy → teal → green ramp. Reads low → high within the dashboard’s core hues; in-bar labels stay legible.
Grouped and simple bars use dark labels at the bar ends; stacked bars use white in-bar labels. Short bars cannot contain a legible white label.
Every drawn bar carries its unweighted sample size in square brackets, in a lighter column headed “n” at the right edge of the figure (stacked rows: one per row; dumbbells: one column per category; National/Average: in the legend), with a footnote explaining the brackets. Shows how much data sits behind each estimate without crowding the value labels, and lines the sample sizes up so they can be compared.
The LCP school-type category never appears. Zero observations in the school file.
Percentages only, never weighted absolute counts. The report’s counts use a weight scaling not supplied with the extract (see Validation).
Assessment results are never split by schooling status. Only ~200 assessed out-of-school children; the extract diverges from the report on this cut (see Validation).
County is a comparison for proficiency indicators only, and never a second comparison. Every other county cut is dominated by sub-50 cells; 47 colour categories are unreadable.
By county, a figure shows the ten highest and ten lowest of the 47 counties, with a gap between them and a footnote saying so; the joint proficiency view ranks counties by the share meeting both English and Mathematics. On a desktop window such a figure takes its natural height and the page scrolls. Forty-seven bars cannot be read at a glance and the extremes carry the comparison; a figure scrolling inside its panel hides that it has been cut.
Income source is shown in five groups (Farming, Casual labour, Self-employment, Formal employment, Transfers and other); the mapping is under Recoding and cleaning. Eleven stacked segments are unreadable and several are each a few per cent; the five keep the distinctions that matter for a household’s livelihood.
A second comparison with two categories (gender, location, residence, refugee status) draws as a dumbbell: one row per group, a dot for each category joined by a line, the values either side and each category’s sample size in its own column. Where one category is suppressed the row keeps the other dot and names the missing one. The difference between the two groups is the point of such a split, and paired bars make the eye compare two lengths instead of reading one gap.
Degenerate comparison pairs are removed (county × region, county × performance band, school type × refugee status). Each county lies wholly inside one region and one band; refugee schools are exactly the refugee school type.
The county performance band is not offered for the proficiency outcomes (English, Mathematics, both, and the joint view), as a first or a second comparison. The band is built from county proficiency, so it would split performance by performance.
School type and mother’s education serve as indicators only, not comparison denominators. 35% and 44% missing respectively.
Children recorded as gender “Other” (n = 4) are excluded from gender comparisons. Four observations cannot support a category estimate.
Invalid dropdown combinations are unreachable, derived from the pre-computed JSON keys. The data is the single source of truth for what can be shown.
County performance bands are rank quintiles of weighted combined proficiency. The delivered outcome variables are binary, so child-level score quintiles cannot be computed from this extract.
The scatter’s education covariates code “secondary or higher” as the top three of the builder’s five bands (Secondary — including secondary-school dropouts and post-primary certificates — Post-secondary cert., Degree +); no years-of-schooling mapping is imposed. Keeps the scatter in lock-step with the builder’s education coding and avoids an arbitrary ordinal-to-years conversion.

Outputs

data/processed/tab2/household.json and school.json — each self-contained (tables plus the metadata that drives the dropdowns) — and data/processed/compare.json for the scatter. A further file, tab2/qa_reference.json, carries the report-replication cuts used for the validation above and is not consumed by the site. The pipeline also retains tab2/fits.json, from an age/proficiency relationship analysis that Compare no longer displays.


← Back to the Compare tab