cassionData Analysis

Back to the lessonLesson 7 of 8What the numbers mean

The area whose cases doubled is the one that improved

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 / 27

    What this lesson covers

    • The curve, and the obvious reading
    • What a case count is a count of
    • The test that distinguishes them
    • Say it in the report, in the sentence next to the number
    • The consequence people miss
    • Where prevalence actually comes from
    • What comes next
    Speaker notes
    Saint-Louis-du-Nord's monthly intake goes from 5.8 cases to 10.2 after July. Nothing about violence in that area changed. A service opened, and a case curve measures whether people can reach a desk — never how many of them needed to.
  2. Slide 2 / 27

    The curve, and the obvious reading — In Python

    import pandas as pd
    
    cases = pd.read_csv("protection-case-management-2024.v1.csv")
    monthly = cases.groupby(["admin2", "opened_month"]).size().unstack(fill_value=0)
    print(monthly)
  3. Slide 3 / 27

    The curve, and the obvious reading — In R

    library(dplyr)
    
    cases |> count(admin2, opened_month) |>
      tidyr::pivot_wider(names_from = opened_month, values_from = n, values_fill = 0)
  4. Slide 4 / 27

    The curve, and the obvious reading — In Python

    area = cases[cases["admin2"] == "Saint-Louis-du-Nord"]
    month = area["opened_month"].str[5:].astype(int)
    before = (month <= 6).sum() / 6
    after = (month >= 7).sum() / 6
    print(f"Jan-Jun: {before:.1f} cases a month")
    print(f"Jul-Dec: {after:.1f} cases a month  ({after / before - 1:+.0%})")
    Speaker notes
    One area's line goes up and stays up.
  5. Slide 5 / 27

    The curve, and the obvious reading — In R

    cases |>
      filter(admin2 == "Saint-Louis-du-Nord") |>
      mutate(half = if_else(as.integer(substr(opened_month, 6, 7)) <= 6, "H1", "H2")) |>
      count(half) |> mutate(per_month = n / 6)
  6. Slide 6 / 27

    The curve, and the obvious reading

    • 5.8 cases a month before July, 10.2 after — a 74% rise — while no other area moves by more than eleven points either way
    Speaker notes
    5.8 cases a month before July, 10.2 after — a 74% rise, while no other area moves by more than eleven points either way. The obvious reading is that protection incidents in Saint-Louis-du-Nord rose 74% in the second half of the year. That reading is wrong, and it is the single most common misuse of protection data.
  7. Slide 7 / 27

    What a case count is a count of

    The count depends onWhich changes when
    A service existing within reachOne opens, one closes, a road is cut
    People knowing it existsAn outreach campaign runs
    People being willing to discloseTrust rises or falls; a bad experience circulates
    Someone opening a fileStaffing, workload, referral practice
    Incidence in the population—
    Speaker notes
    A case exists when a person reached a service, was willing to disclose, and a caseworker opened a file. So the count is a product of four things, only the last of which is what people read it as:
  8. Slide 8 / 27

    What a case count is a count of

    • Every one of the first four moved in Saint-Louis-du-Nord in July, because a service opened — The fifth is not measured…
    Speaker notes
    Every one of the first four moved in Saint-Louis-du-Nord in July, because a service opened. The fifth is not measured by this file and cannot be.
  9. Slide 9 / 27

    What a case count is a count of — In Python

    print("Case count = incidence x reporting rate x service availability x recording")
    print("A change in the product does not tell you which factor moved.")
  10. Slide 10 / 27

    What a case count is a count of — In R

    # One equation, five unknowns, one observation.
  11. Slide 11 / 27

    The test that distinguishes them

    • Did anything change in the service? — The strongest evidence and the least statistical
    • Did the composition change? — Saint-Louis-du-Nord's general protection share goes from 31.4% to 41.0% while GBV falls…
    Speaker notes
    You cannot prove the curve is a reporting effect from the curve alone. You can gather evidence, and three checks are usually available. Did anything change in the service? The strongest evidence and the least statistical. A new service, a new outreach worker, a changed intake form or a partner closing all produce a step change with a date attached. Did the composition change? Saint-Louis-du-Nord's general protection share goes from 31.4% to 41.0% while GBV falls from 40.0% to 32.8% — the new arrivals skew toward the least stigmatised category, which is what improved access looks like rather than what a surge in violence looks like.
  12. Slide 12 / 27

    The test that distinguishes them — In Python

    def mix(frame):
        return frame["case_category"].value_counts(normalize=True).round(3)
    
    print("before July:", mix(area[month <= 6]).to_dict())
    print("after July: ", mix(area[month >= 7]).to_dict())
  13. Slide 13 / 27

    The test that distinguishes them — In R

    cases |> filter(admin2 == "Saint-Louis-du-Nord") |>
      mutate(half = if_else(as.integer(substr(opened_month, 6, 7)) <= 6, "H1", "H2")) |>
      count(half, case_category) |> mutate(share = n / sum(n), .by = half)
  14. Slide 14 / 27

    The test that distinguishes them

    • Did other areas move? — A rise confined to one area with an administrative explanation is a reporting effect
    Speaker notes
    Did other areas move? A rise confined to one area with an administrative explanation is a reporting effect. A rise across every area at the same time is more likely to be real, or a change in the reporting system.
  15. Slide 15 / 27

    The test that distinguishes them — In Python

    halves = cases.assign(half=(cases["opened_month"].str[5:].astype(int) > 6))
    shift = halves.groupby(["admin2", "half"]).size().unstack()
    shift["change"] = shift[True] / shift[False] - 1
    print((shift["change"] * 100).round(1).sort_values())
  16. Slide 16 / 27

    The test that distinguishes them — In R

    cases |> mutate(half = as.integer(substr(opened_month, 6, 7)) > 6) |>
      count(admin2, half) |> tidyr::pivot_wider(names_from = half, values_from = n)
  17. Slide 17 / 27

    The test that distinguishes them

    • One area up 74.3%; the other five range from −9.4% to +11.3% — A single area moving seven times as far as the widest of…
    Speaker notes
    One area up 74.3%; the other five range from −9.4% to +11.3%. A single area moving seven times as far as the widest of the others has an administrative cause, and the job is to find it rather than to publish an incidence claim.
  18. Slide 18 / 27

    Say it in the report, in the sentence next to the number — Example

    Cases opened, Saint-Louis-du-Nord
    
      Jan-Jun    35 cases    5.8 per month
      Jul-Dec    61 cases   10.2 per month   +74%
    
      A case management service opened in the area in July. This figure measures
      the number of people who reached a service and disclosed; it is not a
      measure of the number of incidents. The rise is consistent with improved
      access and cannot be read as a rise in violence.
    
      The other five areas moved between -9% and +11% over the same period.
  19. Slide 19 / 27

    Say it in the report, in the sentence next to the number

    • The disclaimer belongs beside the number, not in a footnote — A protection case curve without that sentence will be…
    Speaker notes
    The disclaimer belongs beside the number, not in a footnote. A protection case curve without that sentence will be quoted as an incidence trend within a week, usually by someone quoting your report accurately.
  20. Slide 20 / 27

    The consequence people miss — In Python

    outcomes = pd.DataFrame({
        "observation": ["cases rise", "cases fall"],
        "good reading": ["outreach and access improved",
                         "incidents fell"],
        "bad reading": ["violence increased",
                        "service became unreachable, or trust was lost"],
    })
    print(outcomes)
    Speaker notes
    If a case count measures access, then a programme that succeeds should see its case count rise, and a falling case count is ambiguous at best.
  21. Slide 21 / 27

    The consequence people miss — In R

    # The same number supports opposite conclusions. The context decides.
  22. Slide 22 / 27

    The consequence people miss

    • So a protection programme cannot use case volume as a performance indicator in either direction — and the indicators…
    Speaker notes
    So a protection programme cannot use case volume as a performance indicator in either direction, and the indicators that survive are the ones this course has been building: pathway completion, time to service, caseload, closure reasons. Each of those has a denominator that is not the population.
  23. Slide 23 / 27

    Where prevalence actually comes from

    • Population-based prevalence surveys — designed for the purpose, with specialised interviewer training and ethical…
    • Never from service data — at any level of sophistication
    Speaker notes
    Named plainly, because the question will be asked. Population-based prevalence surveys, designed for the purpose, with specialised interviewer training and ethical protocols that a service dataset does not have. They are expensive, infrequent and the only instrument that answers the question. Never from service data, at any level of sophistication. No adjustment for reporting rate rescues a denominator that is "people who reached a service".
  24. Slide 24 / 27

    Where prevalence actually comes from — In Python

    print("Question: how many women in this district experienced violence this year?")
    print("Answerable from this dataset: no")
    print("Instrument that answers it: a population-based prevalence survey")
  25. Slide 25 / 27

    Where prevalence actually comes from — In R

    # Saying "we cannot answer that with this" is the answer.
  26. Slide 26 / 27

    What comes next

    • The last lesson assembles everything into a protection report — including the section that states which analyses were requested and declined, and why that section belongs in the document rather than in an email nobody keeps.
    Speaker notes
    The last lesson assembles everything into a protection report — including the section that states which analyses were requested and declined, and why that section belongs in the document rather than in an email nobody keeps.
  27. Slide 27 / 27

    Where this goes next

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