Pythonで世界銀行のデータを取得する

Narwhal APIは、CC BY 4.0で提供される世界銀行WDIの年次指標1,489件を索引化しています。Pythonで世界銀行データを取得するには、指標を検索し、そのIDテンプレートに小文字の国コードを追加して、APIキーで観測値をリクエストします。レスポンスには期間、小数文字列の値、出典表示、ライセンスURLが含まれます。取得可能な履歴期間と、キャッシュにないデータの1日あたりの取得枠はプランによって決まります。

APIを使う方法

  1. 無料のキーを取得してPythonを準備する 新規登録でアカウントを作成し、APIキーを取得して、Pythonを実行するシェルでNARWHAL_API_KEYを設定してください。プレースホルダーを自分のキーに置き換えます。HTTP呼び出し用にrequests、DataFrame用にpandasをインストールしてください。各リクエストはAuthorizationヘッダーでキーを使用します。最後の手順にある完全なスクリプトは、環境変数からキーを読み取ります。
    依存ライブラリをインストールしてキーを設定する
    python -m pip install requests pandas
    export NARWHAL_API_KEY="replace-with-your-key"
  2. 指標を検索する source=wdiを指定して、カタログでgdp per capitaを検索してください。各結果のid_templateとタイトルを出力し、必要な指標を選びます。カタログ検索はすべてのプランで利用でき、ソースへの呼び出しは行いません。検索語句内のスペースはparams引数で処理します。検索結果は指標を示します。国は、次に組み立てる系列IDに指定します。
    世界銀行の指標テンプレートを検索する
    import os
    import requests
    
    BASE_URL = "https://api.narwhalapi.com"
    headers = {
        "Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"
    }
    response = requests.get(
        f"{BASE_URL}/v1/economics/catalogue",
        headers=headers,
        params={"q": "gdp per capita", "source": "wdi"},
        timeout=10,
    )
    response.raise_for_status()
    catalogue = response.json()
    for hit in catalogue["results"]:
        print(hit["id_template"], hit["title"])
  3. テンプレートに国を追加する 選んだテンプレートの{country}を、小文字のISO 3166-1 alpha-3コードに置き換えてください。インドネシアはidnを使用します。世界銀行のIDはwdi:<indicator>/<iso3>形式で、指標と国の間にスラッシュを含みます。完全なIDをidクエリパラメーターで渡してください。コード例は最初の検索結果を選択するため、使用する前に出力されたタイトルを確認してください。
    国別の系列IDを組み立てる
    if not catalogue["results"]:
        raise SystemExit("No matching indicators found.")
    selected = catalogue["results"][0]
    series_id = selected["id_template"].replace("{country}", "idn")
    print(series_id)
  4. 年次観測値を読み取る そのIDの観測値をリクエストしてください。年次の期間にはYYYYを使用します。任意のstartとendは指定した境界を含みます。レスポンスの取得件数の上限は最大1,000観測値、デフォルトは100です。next_cursorに値がある場合は、cursorとして渡して取得を続けてください。上限を増やしてもプランの履歴期間は延長されず、欠測年はレスポンスに含まれません。
    選択した系列を読み取る
    response = requests.get(
        f"{BASE_URL}/v1/economics/catalogue/series/observations",
        headers=headers,
        params={"id": series_id, "limit": 1000},
        timeout=10,
    )
    response.raise_for_status()
    observations = response.json()["observations"]
  5. DataFrameを作成する 観測値からDataFrameを作成し、periodを整数、valueを浮動小数点数に変換してください。値は小数文字列で返されます。十進数演算が必要な場合は、float()の代わりにDecimalを使用してください。レスポンスの単位ラベルを分析とともに保持してください。指標のタイトルには、値が何を測定しているかが記載されています。この変換は欠測を埋めたり、欠測年の観測値を生成したりしません。
    期間と値を変換する
    import pandas as pd
    
    frame = pd.DataFrame(observations, columns=["period", "value"])
    frame["period"] = frame["period"].astype(int)
    frame["value"] = frame["value"].map(float)
    print(frame)
  6. 国をまとめて取得し、リクエストエラーを処理する この完全なスクリプトを実行すると、例で使用するGDP系列と、インドネシアおよびカナダの最新値をまとめて取得できます。IDはカンマで連結してください。最新値エンドポイントには、異なるIDを1から50件指定できます。返された系列ごとに1呼び出しとして、一括で計上されます。スクリプトは各国の期間と値を出力し、取得できなかったIDを報告します。400、404、429 fetch_limit_reachedのレスポンスでは、エラーメッセージを表示して停止します。
    GDP履歴を読み取り、最新値をまとめて取得する
    import os
    import requests
    import pandas as pd
    
    BASE_URL = "https://api.narwhalapi.com"
    HEADERS = {
        "Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"
    }
    
    def get_json(path, params):
        response = requests.get(
            f"{BASE_URL}{path}",
            headers=HEADERS,
            params=params,
            timeout=10,
        )
        try:
            response.raise_for_status()
        except requests.HTTPError:
            problem = response.json()
            code = problem.get("code", "unknown_error")
            if response.status_code == 429 and code == "fetch_limit_reached":
                retry_after = response.headers.get("Retry-After")
                raise SystemExit(
                    f"Uncached fetch allowance used. Retry-After: {retry_after}"
                )
            if response.status_code in (400, 404):
                raise SystemExit(f"{code}: {problem.get('detail', '')}")
            raise
        return response.json()
    
    series_id = "wdi:ny.gdp.mktp.cd/idn"
    rows = []
    params = {"id": series_id, "limit": 1000}
    while True:
        payload = get_json(
            "/v1/economics/catalogue/series/observations", params
        )
        rows.extend(payload["observations"])
        cursor = payload.get("next_cursor")
        if not cursor:
            break
        params["cursor"] = cursor
    
    frame = pd.DataFrame(rows, columns=["period", "value"])
    frame["period"] = frame["period"].astype(int)
    frame["value"] = frame["value"].map(float)
    print(frame)
    
    countries = ("idn", "can")
    ids = [f"wdi:ny.gdp.mktp.cd/{country}" for country in countries]
    batch = get_json(
        "/v1/economics/catalogue/latest",
        {"ids": ",".join(ids)},
    )
    for observation in batch["observations"]:
        country = observation["id"].rsplit("/", 1)[1]
        print(country, observation["period"], observation["value"])
    for missing in batch["missing"]:
        print("Missing:", missing)

インドネシアのGDPの例はどのように読み取ればよいですか。

系列wdi:ny.gdp.mktp.cd/idnは、インドネシアの名目米ドル建てGDPです。27 October 2026にProのキーでlimit=3を指定したリクエストから、これらの観測値が返されました。この例はGDP総額を使用します。1人当たりGDPが必要な場合は、カタログ検索で得たテンプレートを使用してください。

GDPレスポンスから記録した観測値
[
  {"period": "1967", "value": "5667756627.92093"},
  {"period": "1968", "value": "7076465299.81141"},
  {"period": "1969", "value": "8337423312.88344"}
]

1967の値は、float("5667756627.92093")でDataFrame内の数値処理用に変換できます。十進数表現も必要な場合は、元の文字列を保持してください。レスポンスには世界銀行WDIの出典表示とCC BY 4.0のライセンスURLが含まれます。使用するデータとともに、出典表示とライセンス情報を保持してください。

Freeのキーで数年分しか返されないのはなぜですか。

Freeの履歴期間は12か月で、年次系列では最新5観測値を最低限取得できます。Narwhalは、プランの履歴期間とこの最低件数のうち、観測値が多くなる方を適用します。そのため、年次系列では通常の履歴期間外の値が大半を占める場合でも、複数の観測値が保持されます。この年次系列の最低件数は、すべてのプランに適用されます。

プラン別の上限:

プランアカウントごとのUTC日あたりのキャッシュ未格納データ取得回数履歴範囲
無料10過去12か月、年次は少なくとも最新5観測値
Basic100過去5年、年次は少なくとも最新5観測値
Pro1,000全期間の履歴

指定範囲が許可された履歴期間よりすべて前の場合は、403 plan_upgrade_requiredを返します。年次系列では最低件数を考慮できるよう、Narwhalは系列を読み込んだ後にその範囲を確認します。プランの詳細で、分析に必要な履歴期間を選んでください。

429 fetch_limit_reachedエラーは何を意味しますか。

アカウントの1日あたりの取得枠を使い切っており、リクエストにキャッシュ外のデータ取得が必要な状態です。再試行する前にRetry-Afterを確認してください。取得枠は00:00 UTCにリセットされます。上限に達した後も、キャッシュ済みの系列は応答します。世界銀行データのキャッシュ期間は24時間から7日なので、再度リクエストしても必ずしもデータ取得が発生するわけではありません。

400 invalid_series_idの場合は、指標、スラッシュ、小文字の国コードを確認してください。400 invalid_queryはクエリが無効であることを意味します。404 not_foundは、指標が索引に存在しないことを意味する場合があります。Narwhalはその結果を24時間保持します。リクエストを繰り返す前に、IDをカタログの検索結果と照合してください。

古いキャッシュを返す応答と、400、404、503のレスポンスは計上されません。ソースを利用できず、キャッシュもない場合、NarwhalはRetry-Afterとともに503 upstream_busyを返します。再試行の処理はキャッシュと429への対応を参照してください。

公開。

次のステップ