MZQMohd Zamin Quadri
All work

Official statistics in R

Twenty-Four Years, Half a Point

How Europeans travel, from official data.

Role
Project author
Classification
Reproducible experiment
Inspect repository
One axis of car share carrying both comparisons: what 24 years of policy moved, and what differs between two countries in a single year.One axis of car share of inland passenger transport, running from 60 to 100 with the truncation stated on the axis because every observed value lies above 60. The EU aggregate is marked at both ends of the comparison, 82.0 in 2000 and 82.5 in 2024, and the distance between them is labelled as half a point in twenty-four years. A second span then opens across the same axis for a single year, from Hungary at 66.9 to Montenegro at 97.8, which is 30.9 points. The two distances are then redrawn from a common origin so their lengths can be compared directly, and the country spread is about sixty-two times the policy span. Germany is marked at 84.1, twelfth of thirty-four. The sequence closes on the movement that did occur: rail gained share in 14 of 32 countries, the largest single gain being Switzerland at 7.3 points.
  1. Problem

    Typed findings go stale when data updates.

  2. How it was solved

    Every number is recomputed from a pinned dataset.

    1. Eurostat
    2. Pinned hash
    3. Recompute
    4. Report
  3. Result

    +0.5

    points of car share in 24 years

    • 200082.0%
    • 202482.5%
  4. Built with

    • R
    • Quarto
    • ggplot2
    • Docker
    See the evidence on GitHub
One axis of car share of inland passenger transport, running from 60 to 100 with the truncation stated on the axis because every observed value lies above 60. The EU aggregate is marked at both ends of the comparison, 82.0 in 2000 and 82.5 in 2024, and the distance between them is labelled as half a point in twenty-four years. A second span then opens across the same axis for a single year, from Hungary at 66.9 to Montenegro at 97.8, which is 30.9 points. The two distances are then redrawn from a common origin so their lengths can be compared directly, and the country spread is about sixty-two times the policy span. Germany is marked at 84.1, twelfth of thirty-four. The sequence closes on the movement that did occur: rail gained share in 14 of 32 countries, the largest single gain being Switzerland at 7.3 points.

Reproducible experiment / Official statistics

The share of inland passenger distance taken by car in the EU was 82.0 per cent in 2000. In 2024 it is 82.5. The finding is the absence of a finding, which is harder to publish than a trend.

What 24 years moved+0.5 points

The chain of commitments behind a null result

the one free choiceCommitted responseRetrieved once and committed,so the report has a fixed…Pinned by hashRecomputed in CI. An upstreamedit fails rather than slips…JSON-stat decodedDimension indices unpacked byhand rather than through a…Year chosen by coverageBy which countries report it,not by which is most recent.One render passProse and figures from thesame objects, so they cannot…Half a point82.0% to 82.5% acrosstwenty-four years. The absence…
A finding of no change is only readable if the route to it was fixed in advance. The hash is recomputed in CI and the comparison year is chosen by coverage - the one decision free enough to manufacture a trend.

This diagram in words

  1. Committed response source — Retrieved once and committed, so the report has a fixed input.
    R
  2. Pinned by hash gate — Recomputed in CI. An upstream edit fails rather than slips through.
    GitHub Actions
  3. JSON-stat decoded process — Dimension indices unpacked by hand rather than through a helper.
    jsonlite
  4. Year chosen by coverage gate — By which countries report it, not by which is most recent.
  5. One render pass process — Prose and figures from the same objects, so they cannot disagree.
    Quarto · ggplot2
  6. Half a point artifact — 82.0% to 82.5% across twenty-four years. The absence is the result.

01 / 7Car share, 60 to 100 per centThe axis starts at 60 because every observed value is above it. A truncated axis is a decision.

Axis
60 to 100 per cent
Why not zero
Every observed value is above 60; a zero baseline hides the comparison
Countries reporting
35
One axis of car share of inland passenger transport, running from 60 to 100 with the truncation stated on the axis because every observed value lies above 60. The EU aggregate is marked at both ends of the comparison, 82.0 in 2000 and 82.5 in 2024, and the distance between them is labelled as half a point in twenty-four years. A second span then opens across the same axis for a single year, from Hungary at 66.9 to Montenegro at 97.8, which is 30.9 points. The two distances are then redrawn from a common origin so their lengths can be compared directly, and the country spread is about sixty-two times the policy span. Germany is marked at 84.1, twelfth of thirty-four. The sequence closes on the movement that did occur: rail gained share in 14 of 32 countries, the largest single gain being Switzerland at 7.3 points.
Read the full background

Problem

Why this work exists

A report that types its findings into its prose can be correct on the day it is written and wrong the next time the data is refreshed, with nothing to catch the gap. And the finding here is an absence: the share of inland passenger distance taken by car in the EU has barely moved since 2000, which is harder to publish honestly than a trend, because a flat line read on its own says nothing happened rather than this is the result.

Contribution

What I can claim

Decoded the JSON-stat response by hand rather than using the Eurostat package, committed the raw response with a pinned SHA-256 that CI recomputes, and wrote every figure in the prose as a computed value rather than a literal, so the text and the charts are produced from one pass over the same data.

Method

A report that can be re-run against its own source

Descriptive statistics are the easiest thing to publish and the hardest to trust later, because the numbers in the prose and the numbers in the data drift apart quietly.

  1. Retrieve

    The source table is fetched and the response itself committed, so what the report was written against is in the repository rather than on somebody else's server.

  2. Pin

    It is fixed by checksum, recomputed in continuous integration.

  3. Decode

    The response format is unpacked by hand rather than through a convenience wrapper, which keeps the transformation from source to table readable and reviewable.

  4. Select

    The comparison year is chosen by coverage rather than by recency, because the most recent year is the one where the fewest countries have reported.

  5. Render

    Prose and figures are produced in the same pass from the same table, so a sentence and the chart beside it cannot disagree.

  6. What this does not show

    This is descriptive. It measures shares and says nothing about why any of them moved or stayed put, and the cross-country differences it shows are differences in geography, settlement and policy that it makes no attempt to separate.

How it was built

System

Workflow and decisions

One Quarto document is the whole pipeline: it reads the committed response, decodes it, derives every figure, and emits the prose and the charts together. There is no step in which a number is copied from one artefact into another.

  1. 1Retrieve the table and commit the response
  2. 2Pin it by SHA-256, recomputed in CI
  3. 3Decode JSON-stat by hand
  4. 4Select the comparison year by coverage
  5. 5Render prose and figures from one pass
  • R
  • Quarto
  • ggplot2
  • jsonlite
  • Docker
  • GitHub Actions

Evidence

What is actually versioned

What 24 years moved+0.5 points

The EU27_2020 car share was 82 per cent in 2000 and 82.5 in 2024. Whatever has changed in European transport policy over that period, it has not changed what share of distance is driven.

What a border moves30.9 points

In 2024 the spread across countries runs from 66.9 per cent in Hungary to 97.8 in Montenegro. Germany is 84.1, ranking 12 of 34.

Rail14 of 32 countries

Gained share between each country's own first and last reported year. The largest gain is Switzerland, up 7.3 points.

ReproducibilityPinned and recomputed

Eurostat tran_hv_psmod, retrieved 2026-10-18 and committed with its SHA-256. CI recomputes the digest and fails if it stops matching the README and the provenance file, so the snapshot, the prose and the figures cannot drift apart.

How the work is checked

Quality controls

How the work is checked

  • Every figure in the prose is computed at render time; none is typed in
  • The raw API response is committed, so the report renders offline and reproducibly
  • The comparison year is selected by reporting coverage rather than by taking the latest year present
  • JSON-stat is decoded by hand, which is the part of the work worth showing, so the Eurostat package is deliberately not a dependency
  • The output is one self-contained HTML file with the figures and CSS inlined

Limitations

Where the evidence stops

  • A descriptive report. It measures shares and says nothing about why any of them moved or did not
  • Modal split is a share of distance, so a country can hold its car share steady while total distance travelled rises or falls underneath it
  • Coverage is uneven across countries and years, which is why the single-year comparisons use one year chosen by coverage rather than the latest available
  • One snapshot of one table, pinned on a date. It is reproducible rather than live
What this changed in my practice

What this changed in my practice

An absence is a finding, but it only reads as one next to something that did change. The flat EU line means nothing on its own and means a great deal beside a 30.9 point spread between two countries in a single year.

Next evidence milestone: A second table. Modal split is a share, and a share cannot distinguish a country where driving fell from one where everything else rose faster. Passenger-kilometres alongside it would separate the two.