cassionData Analysis

Back to the lessonLesson 1 of 8The project on disk

Three kinds of file, and only one of them is editable

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

    What this lesson covers

    • The layout
    • The test that decides whether you have it right
    • Make the raw data unwriteable, literally
    • Naming, which is provenance
    • What goes in the repository
    • The README that is actually read
    • Report it whole
    • What comes next
    Speaker notes
    Raw data is read-only, derived data is disposable, and code is the only thing anyone edits. Getting that boundary wrong is how an analysis becomes irreproducible in a way nobody notices for eleven months.
  2. Slide 2 / 21

    The layout — Example

    project/
      data/
        raw/            never edited, never written to, ideally chmod -w
        reference/      lookup tables, thresholds, admin boundary codes
      R/  or  src/      the only files anyone edits
      outputs/
        derived/        cleaned data, disposable
        figures/        charts and the CSV of values behind each
        reports/        rendered documents
      tests/
      README.md
      environment lock  uv.lock or renv.lock
  3. Slide 3 / 21

    The layout

    • Three kinds of file and the distinction is not tidiness
    • Raw data is read-only — The export from CommCare, the CSV from DHIS2, the spreadsheet the ministry sent
    • Derived data is disposable — Anything in outputs/ can be deleted at any moment and reproduced by running the code
    • Code is the only thing edited — Every correction, every recode, every exclusion is a line of code, which means it is…
    Speaker notes
    Three kinds of file and the distinction is not tidiness. Raw data is read-only. The export from CommCare, the CSV from DHIS2, the spreadsheet the ministry sent. Once it lands in data/raw/ nothing writes to it and nobody opens it in Excel to fix a typo — a corrected raw file is a file whose provenance you have destroyed. Derived data is disposable. Anything in outputs/ can be deleted at any moment and reproduced by running the code. If deleting outputs/ loses something, that something was not derived and belongs somewhere else. Code is the only thing edited. Every correction, every recode, every exclusion is a line of code, which means it is visible, reviewable and rerunnable.
  4. Slide 4 / 21

    The test that decides whether you have it right — Shell

    rm -rf outputs/ && make all      # or: python run.py, Rscript run.R
    git status --short               # should be empty
  5. Slide 5 / 21

    The test that decides whether you have it right

    • Delete every output, rerun, and the repository should look untouched — That single command is the whole of…
    • Three ways it usually fails — and each names something real:
    • A file in outputs/ that nothing produces — Someone made it by hand, once, and every run since has depended on it
    • A step that only runs interactively — A cell in a notebook, a line pasted into a console, a manual download
    • Something that must be run in a particular order and does not say so — The pipeline works on your machine because you…
    Speaker notes
    Delete every output, rerun, and the repository should look untouched. That single command is the whole of reproducibility as an operational property, and it is uncomfortable the first time. Three ways it usually fails, and each names something real: A file in outputs/ that nothing produces. Someone made it by hand, once, and every run since has depended on it. It is raw data wearing the wrong name. A step that only runs interactively. A cell in a notebook, a line pasted into a console, a manual download. If it is not in a script, it did not happen. Something that must be run in a particular order and does not say so. The pipeline works on your machine because you know the order.
  6. Slide 6 / 21

    Make the raw data unwriteable, literally — Shell

    chmod -R a-w data/raw/
  7. Slide 7 / 21

    Make the raw data unwriteable, literally — In R

    # In R, the equivalent discipline is a function that only ever reads:
    read_raw <- function(name) readr::read_csv(file.path("data/raw", name))
  8. Slide 8 / 21

    Make the raw data unwriteable, literally

    • It costs one command and prevents the failure it names — An accidental to_csv("data/raw/survey.csv") in a notebook is…
    • Where the raw file is large or restricted, commit its checksum instead
    Speaker notes
    It costs one command and prevents the failure it names. An accidental to_csv("data/raw/survey.csv") in a notebook is the most destructive thing an analyst does, it produces no error, and nothing downstream can detect it afterwards. Where the raw file is large or restricted, commit its checksum instead.
  9. Slide 9 / 21

    Make the raw data unwriteable, literally — In Python

    import hashlib, pathlib
    
    def fingerprint(path: pathlib.Path) -> str:
        return hashlib.sha256(path.read_bytes()).hexdigest()[:16]
    
    print(fingerprint(pathlib.Path("data/raw/survey-2025.csv")))
  10. Slide 10 / 21

    Make the raw data unwriteable, literally — In R

    tools::md5sum("data/raw/survey-2025.csv")
  11. Slide 11 / 21

    Make the raw data unwriteable, literally

    • A checksum in the repository turns "is this the same export?" into a question with an answer — Ninety per cent of "the…
    Speaker notes
    A checksum in the repository turns "is this the same export?" into a question with an answer. Ninety per cent of "the numbers changed and I do not know why" is a source file that changed and nobody noticed.
  12. Slide 12 / 21

    Naming, which is provenance

    NameWhat it tells you
    survey.csvNothing
    final_survey_v2_FINAL.xlsxThat there are several and this one won an argument
    household-survey-2025.v1.csvWhat, when, and which version
  13. Slide 13 / 21

    Naming, which is provenance

    • Version by filename, never by overwriting — This platform's datasets do exactly that: a correction ships as .v2.csv…
    • That is why the dataset files can be cached immutably — and why the course PDFs — which are regenerated in place —…
    Speaker notes
    Version by filename, never by overwriting. This platform's datasets do exactly that: a correction ships as .v2.csv and never replaces .v1.csv, because a notebook pinned to v1 has to keep reproducing. That is why the dataset files can be cached immutably, and why the course PDFs — which are regenerated in place — deliberately cannot be.
  14. Slide 14 / 21

    What goes in the repository

    InOut
    Code, every scriptRaw data with personal information
    The environment lock fileAnything above about 50 MB
    Small reference tablesCredentials, tokens, connection strings
    Generated outputs the build cannot rebuild.Rhistory, __pycache__, .DS_Store
    A READMEOutputs that regenerate in seconds
  15. Slide 15 / 21

    What goes in the repository

    • The fourth row is a judgement rather than a rule — This platform commits its generated PDFs, decks and figures —…
    Speaker notes
    The fourth row is a judgement rather than a rule. This platform commits its generated PDFs, decks and figures — because the deploy runs on Cloudflare with no TeX and no Python, so a contributor without the toolchain can still ship a content change. Commit a generated artefact when rebuilding it is not available to everyone who needs it, and not otherwise.
  16. Slide 16 / 21

    The README that is actually read — Example

    # Nutrition surveillance analysis, Artibonite
    
    ## What this produces
    A quarterly GAM estimate by commune, and the figures in the cluster report.
    
    ## Run it
        uv sync
        uv run python run.py
    
    ## Where the data comes from
    data/raw/muac-screening-*.csv — monthly export from the screening database,
    downloaded by the M&E officer on the 5th. Checksums in data/raw/CHECKSUMS.
    
    ## What you need to know
    Commune names arrive spelled four ways; normalisation is in src/clean.py and
    must run before anything else.
    Speaker notes
    Four sections, and it goes stale less often than a long one.
  17. Slide 17 / 21

    The README that is actually read

    • The last section is the one that saves a successor a week — It is the knowledge that lives in your head, and the…
    Speaker notes
    The last section is the one that saves a successor a week. It is the knowledge that lives in your head, and the handover lesson is about getting the rest of it out.
  18. Slide 18 / 21

    Report it whole — Example

    Analysis reproducibility
    
      Raw exports are read-only under data/raw/ with SHA-256 checksums committed.
      All cleaning, exclusion and recoding is in version-controlled code; no raw
      file has been edited.
    
      Every output in outputs/ is reproducible by `uv run python run.py` from a
      clean checkout. Deleting outputs/ and rerunning leaves the repository
      unchanged.
    
      Dataset files are versioned by filename. The v1 file referenced by the
      March report has not been modified; the correction ships as v2.
  19. Slide 19 / 21

    Report it whole

    • The second paragraph is the claim to make and the one to test before making — It is checkable in one command, and an…
    Speaker notes
    The second paragraph is the claim to make and the one to test before making. It is checkable in one command, and an analysis that cannot pass it should say so rather than claim otherwise.
  20. Slide 20 / 21

    What comes next

    • Version control is what makes "the only thing edited is code" into a history you can read.
    Speaker notes
    Version control is what makes "the only thing edited is code" into a history you can read. The next lesson is about using git on analysis work — and about the one thing that must never enter a repository holding programme data, because git is designed to never forget.
  21. Slide 21 / 21

    Where this goes next

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