Build the dataset

Coding Lesson 2 · Math Camp 2026

API 209

Before we begin

ARRIVAL PROMPT

If two analysts download “the same” public indicator one year apart, should their files be identical?

Choose yes, no, or “it depends.” Write the reason that would most affect your trust.

2 MINUTES

Build the dataset

WED AUG 19 · 3-5 PM

Follow one public indicator from source to analysis table, then supervise an agent-assisted update without erasing the trail.

Today

  1. Reconstruct the data pipeline.
  2. Use dplyr verbs with a purpose.
  3. Test keys, joins, types, ranges, and missingness.
  4. Document provenance.
  5. Write and review an agent update contract.

By 5 PM

  • Explain raw, derived, analysis, and output layers.
  • Build a small analysis table with readable R.
  • Test the iso3c + year key.
  • Diagnose a join that changes the row count.
  • Compare a frozen file with a later release.
  • Record source, indicator code, unit, years, and retrieval date.

Yesterday’s evidence inventory

Your inventory named:

  • the unit,
  • the variables,
  • the years,
  • the missingness,
  • one limitation.

Today we ask a harder question: How did those columns get into this file?

A dataset is a chain of decisions

RAW

Exact download or API response.

DERIVED

Cleaned, reshaped, and joined tables.

ANALYSIS

Variables and sample for one question.

OUTPUT

Figures, tables, models, and reports.

Chain of custody

Imagine the raw download as evidence arriving in a sealed bag.

  • Raw: preserve exactly.
  • Script: record each examination.
  • Derived file: show the result of a reproducible step.
  • Key and range checks: confirm nothing silently multiplied, disappeared, or changed meaning.
  • Analysis table: use only after the path can be reconstructed.
Clean-looking data are not necessarily trustworthy. Inspectable data have a defensible history.

Reconstruct the pipeline

Put these actions in order:

  • Save a figure.
  • Download an official API response.
  • Rename and select indicators.
  • Filter an analysis sample.
  • Check the country-year key.
  • Write a source note.

Where should the key test appear more than once?

Frozen does not mean permanent truth

The teaching file ends in 2022 so everyone begins from one reference point.

A later World Bank release may:

  • add new years,
  • revise older values,
  • improve country coverage,
  • change metadata,
  • leave different indicators ending in different years.

Wide and long

Wide

One country-year per row. Indicators are columns.

Useful for a focused analysis.

Long

One country-year-indicator per row.

Useful for comparing indicators or reshaping.

Tidy data

  • Each variable is a column.
  • Each observation is a row.
  • Each type of observational unit is a table.

Tidy is not the same as complete, correct, or analysis-ready.

Types carry meaning

Type Example Risk
Character "KEN" spelling and whitespace
Numeric 72.4 units and impossible ranges
Integer 2022 accidental arithmetic
Logical TRUE unclear construction rule
Missing NA silent row loss

Inspect before transforming

wdi |>
  summarise(
    rows = n(),
    economies = n_distinct(iso3c),
    first_year = min(year),
    last_year = max(year)
  )

wdi |>
  count(income_level, sort = TRUE)

Six verbs, six questions

Verb Question
select() Which variables belong here?
filter() Which observations belong here?
mutate() What new variable am I defining?
arrange() In what order should I inspect rows?
group_by() Within which groups do I compare?
summarise() Which aggregate answers my question?

Choose the verb

Keep 2015-2022 only.
Create log income.
Count observed mortality by year.
Keep the key and health variables.

Name the first verb you would use for each task. More than one pipeline can be reasonable.

Build the health table

health <- wdi |>
  select(
    iso3c, country, year, income_level,
    gdp_per_capita_ppp, under5_mortality
  ) |>
  filter(year >= 2000) |>
  mutate(log_income = log(gdp_per_capita_ppp))

Every line should correspond to a sentence you can defend.

Predict the row count

The source file has 4,991 rows.

After select(), filter(year >= 2000), and mutate(), how many rows should health have?

  • A. Fewer than 4,991
  • B. Exactly 4,991
  • C. More than 4,991
  • D. Impossible to predict

The key test

stopifnot(
  !anyDuplicated(health[c("iso3c", "year")])
)

This assertion says: no economy appears more than once in the same year.

If it fails, stop before joining or summarizing.

Why duplicate keys are dangerous

Country table

iso3c region
KEN SSA
KEN Africa

Outcome table

iso3c year value
KEN 2022 39

What happens when we join by iso3c?

Join contract

Before a join, state:

  1. The key on the left.
  2. The key on the right.
  3. The expected relationship: one-to-one, many-to-one, or one-to-many.
  4. The expected row count after the join.
  5. How unmatched rows will be inspected.

Diagnose before continuing

duplicates <- country_metadata |>
  count(iso3c) |>
  filter(n > 1)

unmatched <- health |>
  anti_join(country_metadata, by = "iso3c")

anti_join() is a question: which rows have no match?

Missingness is part of the data

health |>
  group_by(year) |>
  summarise(
    observed = sum(!is.na(under5_mortality)),
    missing = sum(is.na(under5_mortality)),
    .groups = "drop"
  )

Coverage can change across time and indicators.

Silent row loss

fit <- lm(
  under5_mortality ~ log_income,
  data = health
)

The model uses only rows observed on both variables.

Which two row counts should you compare before interpreting the result?

A named analysis sample

health <- health |>
  mutate(
    analysis_sample =
      !is.na(under5_mortality) &
      !is.na(log_income)
  )

count(health, analysis_sample)

Named sample rules are easier to inspect than hidden filters.

Five-minute build

For your policy track:

  1. Select the key and two indicators.
  2. Keep 2000-2022.
  3. Create a named analysis sample.
  4. Test the country-year key.
  5. Count missing values by year.

8 MINUTES

Provenance answers five questions

  1. Who published the data?
  2. What exact indicator code and definition were used?
  3. When was the file retrieved?
  4. How was it transformed?
  5. Which version produced the analysis?

Indicator codes are evidence

Friendly name Official code
GDP per capita, PPP NY.GDP.PCAP.PP.KD
Under-five mortality SH.DYN.MORT
Female secondary enrollment SE.SEC.ENRR.FE
Internet use IT.NET.USER.ZS

A friendly label can hide a different unit or denominator.

Write a provenance sentence

Complete a precise sentence:

We use [indicator name and code], published by [source], measured in [unit], for [economies and years], retrieved on [date], and transformed by [script].

4 MINUTES

The agent as data engineer

An agent can help:

  • read API documentation,
  • draft a download function,
  • reshape JSON into a table,
  • add tests,
  • compare file versions,
  • document retrieval steps.

It must not silently overwrite the frozen baseline.

Give agency one rung at a time

READ

Recover the existing pipeline. No edits.

PLAN

Name sources, files, risks, and checks.

BUILD

Create a new dated output. Protect the baseline.

COMPARE

Produce a receipt for additions, revisions, and failures.

At which rung would you stop if the indicator definition changed?

What evidence would you need before continuing?

Weak update prompt

Update the dataset to 2025.

Problems:

  • Not every indicator may reach 2025.
  • The official source is unspecified.
  • Historical revisions are not addressed.
  • The output location is unclear.
  • No checks define success.

Update contract

Goal: Extend one named WDI indicator beyond 2022.
Context: Read the build script and indicator dictionary.
Constraints: Use the official API. Do not overwrite the frozen files.
Preserve the indicator code and unit. Record the retrieval date.
Done when: A new dated file exists, country-year keys are unique,
and a comparison reports new rows, latest year, missingness,
and changed historical values.

Review before run

When the agent proposes code, inspect:

  • the API base URL,
  • indicator code,
  • requested years,
  • retry and error behavior,
  • country metadata filters,
  • output filename,
  • uniqueness checks.

Do not confuse syntactic readability with source validity.

Compare versions

Check Question
New rows Which country-years were added?
Revised rows Which historical values changed?
Coverage Which countries remain missing?
Latest year Does it vary by indicator or country?
Metadata Did names, units, or definitions change?

Human-agent-evidence pass

In pairs, review the update contract and add:

  1. one source check,
  2. one structural check,
  3. one substantive range check,
  4. one comparison with the frozen file.

6 MINUTES

Keep a workshop receipt

For each agent round, record:

  1. Context: what the agent actually read.
  2. Permission: read, plan, edit, run, or network.
  3. Action: exact file change, request, or command.
  4. Observation: diff, status, error, row count, or path.
  5. Decision: continue, revise, reject, or stop.
The receipt is more useful than “the agent updated the data.”

Lab 2 tomorrow

THU AUG 20 · 4-5 PM

You will supervise an update for one indicator and leave with:

  • a dated output or documented failure,
  • a version comparison,
  • a provenance note,
  • one check that caught a problem,
  • one unresolved question.

Exit ticket

Write one sentence for each:

  1. A key protects us from…
  2. A frozen file is useful because…
  3. Before accepting an agent update, I will…

3 MINUTES