9  Constructing the index

We build the composite following the OECD/JRC handbook (OECD and European Commission Joint Research Centre 2008): normalize each indicator, weight it, and aggregate. Every choice here is deliberate and logged; ?sec-robustness then tests how much the ranking depends on them.

The pipeline is registry-driven — it reads the same indicators.yml as the rest of the book, so the method described here is the method that runs.

import sys, pathlib
sys.path.insert(0, str(pathlib.Path("analysis/pipeline")))
from build_index import load_registry, build
import pandas as pd, numpy as np

registry = load_registry()

# Demo data so the book renders before real data lands.
rng = np.random.default_rng(0)
cols = [i["id"] for i in registry["indicators"]]
demo = pd.DataFrame(rng.random((6, len(cols))),
                    index=[f"territory_{i}" for i in range(1, 7)],
                    columns=cols)

result = build(demo, registry)
result[["score", "rank"]]
score rank
territory_1 64.92 1
territory_4 61.51 2
territory_5 51.95 3
territory_3 50.55 4
territory_6 45.85 5
territory_2 45.50 6
Important

The data above is random demo data. No territory is being assessed yet. Real results appear once data/processed/indicators.csv is populated (see Chapter 7 and the data appendix).

TODO: replace min-max + linear aggregation with the chosen normalization and a geometric option; document weights.