cassionData Analysis

Back to the lessonLesson 3 of 8The reference sheet

The reference sheet, field by field

The same deck as the downloads, rendered as a page. Start the slideshow to present it full screen — arrow keys or a click advance one slide, Escape leaves.

Slides · PDFSlides · PowerPoint

  1. Slide 1 / 16

    What this lesson covers

    • The test the sheet has to pass
    • The fields
    • Worked: penta3 coverage
    • The field everyone omits
    • Keep it beside the code
    • Write the exclusions as code, not as prose
    • Version it
    • The two-analyst test, in practice
    • What comes next
    Speaker notes
    One page per indicator, thirteen fields, and a test that tells you when it is finished — hand it to a second analyst and see whether they get your number without asking a question.
  2. Slide 2 / 16

    The test the sheet has to pass

    • An indicator reference sheet is finished when a competent analyst who has never met you can compute your number from it, from the raw data, without asking you a question.
    Speaker notes
    An indicator reference sheet is finished when a competent analyst who has never met you can compute your number from it, from the raw data, without asking you a question. That is the only test worth applying, and it is brutal. Almost every reference sheet in circulation fails it at the same three points: the denominator source is named but not specified, the exclusions are not listed, and nobody wrote down what to do when a reporting unit is silent.
  3. Slide 3 / 16

    The fields

    FieldWhat it holds
    NameIncluding the unit of measure
    DefinitionOne sentence a non-analyst can read
    NumeratorThe exact condition, in words
    DenominatorThe exact population, and where it comes from
    ExclusionsWhat is deliberately left out, and why
    Unit of measurePercent, count, per 1,000, litres per person per day
    DirectionHigher is better, lower is better, or neither
    DisaggregationThe cuts that will be reported, and the minimum cell size

    …

    Speaker notes
    Thirteen fields, most of them a line. A sheet takes twenty minutes and it is never written again.
  4. Slide 4 / 16

    Worked: penta3 coverage — Example (cont.)

    Name              penta3_coverage_percent_monthly
    Definition        The share of the target infant population that received a third
                      dose of pentavalent vaccine in the month.
    Numerator         Third doses of pentavalent vaccine administered, as reported by
                      facilities that submitted a monthly report for that month.
    Denominator       Surviving infants in the catchment, from the MoH population
                      estimates 2024, projected from the 2015 census at 2.4% annual
                      growth, summed across facilities that reported.
    Exclusions        Facility-months with report_submitted = false are excluded from
                      both numerator and denominator. Doses given to children outside
                      the catchment are not separable and remain in the numerator.
    Unit              Percent
    Direction         Higher is better
    Disaggregation    Month, facility type, district. Minimum cell 30 in denominator.
    Frequency         Monthly, reported 6 weeks after month end
    Source            DHIS2 data element PENTA3_DOSES, org unit level 4, monthly
  5. Slide 5 / 16

    Worked: penta3 coverage — Example (cont.)

    Computation       100 * sum(doses) / sum(target_population), over reporting
                      facility-months only. Not the mean of facility-level rates.
    Decision          Whether a district is prioritised for outreach in the next
                      quarterly microplan.
    Limitations       Reporting completeness was 76.5% in 2024 and fell to 29% in
                      August; the figure is a lower bound in any month where
                      completeness is below 90%. Catchments overlap, so facility-level
                      values are unreliable; use district level or above.
  6. Slide 6 / 16

    Worked: penta3 coverage

    • "Over reporting facility-months only. Not the mean of facility-level rates." — Those two sentences settle a difference…
    Speaker notes
    Read the exclusions and the computation rows together, because they are where the two-analyst test is usually failed. "Over reporting facility-months only. Not the mean of facility-level rates." Those two sentences settle a difference of several points and neither is implied by the definition. A ratio of sums and a mean of ratios are different numbers, and both are reasonable readings of "coverage".
  7. Slide 7 / 16

    The field everyone omits

    • It exposes indicators that inform nothing. Some of those are still required — a donor asks for them — and that is a…
    • It exposes indicators that inform two decisions. Coverage used both to prioritise outreach and to trigger a…
    • It sets the precision you need. An indicator that prioritises a district needs to be right about the ranking. One…
    Speaker notes
    Decision informed is missing from most templates in use, and it is the field that does the most work. Filling it in has three effects, and all three are uncomfortable in a useful way.
  8. Slide 8 / 16

    Keep it beside the code — In Python

    import json
    from pathlib import Path
    
    sheet = json.loads(Path("indicators/penta3_coverage.json").read_text())
    
    assert sheet["denominator_source"], "denominator source is required"
    assert sheet["decision_informed"], "an indicator with no decision needs saying so"
    
    numerator = vax.loc[vax["reported"] & (vax["antigen"] == "penta3"),
                        "doses_administered"].sum()
    denominator = vax.loc[vax["reported"] & (vax["antigen"] == "penta3"),
                          "target_population"].sum()
    
    print(f"{sheet['name']}: {100 * numerator / denominator:.1f}")
    Speaker notes
    A reference sheet in a Word file in somebody's mailbox is a reference sheet that drifts. Store it as data next to the script that computes the indicator.
  9. Slide 9 / 16

    Keep it beside the code — In R

    sheet <- jsonlite::read_json(here::here("indicators", "penta3_coverage.json"),
                                 simplifyVector = TRUE)
    
    stopifnot(nzchar(sheet$denominator_source), nzchar(sheet$decision_informed))
    
    vax |>
      filter(report_submitted, antigen == "penta3") |>
      summarise(value = 100 * sum(doses_administered) / sum(target_population))
    Speaker notes
    Two gains. The assertions fail the build when a sheet is incomplete, which is the same move the platform's own content schema makes. And the sheet ships with the result, so a table and its definitions travel together — the habit the foundations course introduced with a definitions.csv beside every output.
  10. Slide 10 / 16

    Write the exclusions as code, not as prose — In Python

    EXCLUSIONS = [
        ("non-reporting facility-months", lambda d: ~d["reported"]),
        ("other antigens", lambda d: d["antigen"] != "penta3"),
    ]
    
    remaining = vax.copy()
    for label, rule in EXCLUSIONS:
        dropped = rule(remaining).sum()
        remaining = remaining[~rule(remaining)]
        print(f"excluded {dropped:>5} rows: {label}")
    print(f"{len(remaining)} rows in the indicator")
    Speaker notes
    The exclusions field is the one most likely to be true in the document and false in the script. Close the gap by generating one from the other.
  11. Slide 11 / 16

    Write the exclusions as code, not as prose — In R

    EXCLUSIONS <- list(
      "non-reporting facility-months" = function(d) !d$report_submitted,
      "other antigens"                = function(d) d$antigen != "penta3"
    )
    
    remaining <- vax
    for (label in names(EXCLUSIONS)) {
      rule <- EXCLUSIONS[[label]]
      cat(sprintf("excluded %5d rows: %s\n", sum(rule(remaining)), label))
      remaining <- remaining[!rule(remaining), ]
    }
    Speaker notes
    The printout is the exclusions field, with counts. Paste it into the sheet and the two cannot disagree.
  12. Slide 12 / 16

    Version it — Example

    version   2.1
    changed   2026-07-28
    change    Denominator restricted to reporting facilities. Previously all
              facilities, with non-reporters counted at their target population,
              which understated coverage by about 23% in August 2024.
    effect    Series revised from 2024-01. Values before v2.1 are not comparable.
    Speaker notes
    An indicator definition changes. When it does, the series breaks, and the break has to be visible.
  13. Slide 13 / 16

    Version it

    • Never silently improve a definition — A coverage figure that rises eight points because the definition changed,…
    Speaker notes
    Never silently improve a definition. A coverage figure that rises eight points because the definition changed, presented in the same chart as previous quarters, is the most convincing wrong finding an M&E system can produce.
  14. Slide 14 / 16

    The two-analyst test, in practice

    • The colleague used the calendar month; you used the reporting month.
    • The colleague computed a mean of facility rates; you computed a ratio of sums.
    • The colleague included the district hospital; your extract excluded it because of an org-unit level filter nobody…
    Speaker notes
    Once a quarter, take an indicator, hand the sheet and the raw extract to a colleague who did not write it, and compare. It takes an hour and it finds things no review of the document does. What it typically surfaces: Every one of those is a sheet that needed one more line. The purpose of the exercise is to find the line, not to find out who was right.
  15. Slide 15 / 16

    What comes next

    • The field that generates more disagreement than the other twelve combined is the denominator.
    Speaker notes
    The field that generates more disagreement than the other twelve combined is the denominator. The next lesson is entirely about choosing one, defending it, and saying honestly what it excludes.
  16. Slide 16 / 16

    Where this goes next

    Read the full lesson, with runnable code Back to the lesson