Files
troupe-standup/wizard-work/ledger/build_gdp_nominal_usd.py
T

71 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""Extract GDP (nominal, current US$) for the top 20 countries, 2023.
Source: World Bank API, indicator NY.GDP.MKTP.CD (GDP, current US$), country:all, date=2023.
Filter: keep only records whose country.id is a real ISO 3166-1 alpha-3 code
(iso3_codes.txt from the Wikipedia ISO3 list), dropping World Bank aggregates.
Artifacts (written alongside this script):
- gdp_nominal_usd_2023.csv (rank, country, iso3, gdp_nominal_usd_billions)
- gdp_nominal_usd_2023.md (markdown table of the same top-20)
"""
import csv
import json
import os
HERE = os.path.dirname(os.path.abspath(__file__))
ISO3_PATH = os.path.join(HERE, "iso3_codes.txt")
JSON_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.json")
CSV_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.csv")
MD_PATH = os.path.join(HERE, "gdp_nominal_usd_2023.md")
TOP_N = 20
with open(ISO3_PATH, "r", encoding="utf-8") as f:
iso3_codes = set(line.strip() for line in f if line.strip())
with open(JSON_PATH, "r", encoding="utf-8") as f:
payload = json.load(f)
records = payload[1] # payload[0] is the metadata envelope
rows = []
for r in records:
country = r.get("country", {})
value = r.get("value")
code = r.get("countryiso3code") # ISO 3166-1 alpha-3; aggregates use non-ISO codes
if value is None or code not in iso3_codes:
continue
rows.append(
{
"country": country.get("value", ""),
"iso3": code,
"gdp_raw_usd": float(value),
}
)
rows.sort(key=lambda x: -x["gdp_raw_usd"])
top = rows[:TOP_N]
with open(CSV_PATH, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["rank", "country", "iso3", "gdp_nominal_usd_billions"])
for i, r in enumerate(top, 1):
writer.writerow([i, r["country"], r["iso3"], round(r["gdp_raw_usd"] / 1e9, 3)])
lines = [
"# Top 20 countries by GDP (nominal, current US$) — 2023",
"",
"Source: World Bank API (`NY.GDP.MKTP.CD`, 2023). Only ISO 3166-1 alpha-3 countries "
"are counted (World Bank aggregates excluded).",
"",
"| Rank | Country | ISO3 | GDP nominal (USD billions) |",
"|---:|---|:--:|---:|",
]
for i, r in enumerate(top, 1):
lines.append(f"| {i} | {r['country']} | {r['iso3']} | {r['gdp_raw_usd'] / 1e9:.3f} |")
with open(MD_PATH, "w", encoding="utf-8") as f:
f.write("\n".join(lines) + "\n")
print(f"PARSED rows={len(rows)} kept_countries={len(top)}")
for r in top:
print(f" {r['country']} ({r['iso3']}) {r['gdp_raw_usd'] / 1e9:.3f}B")