e-Stat APIからのデータ取得と活用

e-Statpython

はじめに

e-Stat APIは、日本の政府統計総合窓口(e-Stat)が提供する公式統計データにプログラムからアクセスするための仕組みです。統計データを自動的に取得・活用したいデータサイエンティストやアプリケーション開発者にとって強力なツールとなります。

APIの種類と機能

1. 統計表情報取得API

統計表情報取得APIは、e-Statで提供されている統計表の情報を検索・取得するためのAPIです。

  • 主な機能:

    • 統計分野やキーワードによる統計表の検索
    • 統計表ID、政府統計コード、調査年月などによる絞り込み
    • 統計表の更新日付や公開状況の確認
    • 統計調査の概要情報の取得
  • ユースケース:

    • 利用可能な統計データの一覧取得
    • 最新の統計表公開状況の確認
    • 特定のテーマに関する統計表の検索

2. メタ情報取得API

メタ情報取得APIは、統計データの構造情報(メタデータ)を取得するためのAPIです。データの意味や構造を理解するために不可欠です。

  • 主な機能:

    • 統計データの項目定義情報の取得
    • 分類項目や地域区分などのコード体系の取得
    • データの階層構造に関する情報の取得
    • 時系列データの時間軸情報の取得
  • ユースケース:

    • データの意味を正確に理解するための項目定義確認
    • 地域コードや産業分類コードなどの対応表取得
    • データの集計レベルや粒度の確認
    • 複雑な統計表の構造把握

3. 統計データ取得API

統計データ取得APIは、実際の統計数値データを取得するためのAPIで、最も頻繁に利用されるAPIです。

  • 主な機能:

    • 統計表の全データまたは条件指定による部分データの取得
    • 地域・時間・項目による絞り込みデータの取得
    • データのCSV/JSON/XML形式での出力
    • 大規模データの分割取得(ページング機能)
  • ユースケース:

    • 時系列分析のための経年データ取得
    • 地域比較のための都道府県別データ取得
    • 特定条件に絞ったデータの抽出
    • 自動データ更新システムの構築

補足: その他のAPI機能

  • データセット取得API: 複数の統計表を横断的に検索・取得
  • 地域・時間コード取得API: 地域コードや時間軸のコード体系を取得
  • 統計分類取得API: 産業分類や職業分類などの分類コード情報を取得

利用開始方法

1. アプリケーションIDの取得

APIを利用するには、まずアプリケーションIDを取得する必要があります:

  1. e-Statポータルサイトでユーザー登録
  2. 「API機能」→「アプリケーションIDの発行」から申請
  3. 審査後、IDが発行されます

2. メタ情報の取得

統計データを取得する前に、まずメタ情報を取得して統計表の構造を理解することが重要です。以下は、メタ情報取得APIを使用する例です:

import requests
import json

# API エンドポイントURL
url = "https://api.e-stat.go.jp/rest/3.0/app/json/getMetaInfo"

# パラメータの設定
params = {
    "statsDataId": "0000010101",  # 人口・世帯に関する統計表ID
    "appId": "あなたのアプリケーションID"
}

# リクエストを送信
response = requests.get(url, params=params)

# 結果を表示
response_data = response.json()

# メタ情報から利用可能な項目を確認
if 'GET_META_INFO' in response_data and 'METADATA_INF' in response_data['GET_META_INFO']:
    metadata = response_data['GET_META_INFO']['METADATA_INF']
    
    # 統計表の基本情報
    table_info = metadata['TABLE_INF']
    print(f"統計表名: {table_info['STATISTICS_NAME']}")
    print(f"表題: {table_info['TITLE']['$']}")
    print(f"公開日: {table_info['OPEN_DATE']}")
    
    # 分類項目の確認
    if 'CLASS_INF' in metadata and 'CLASS_OBJ' in metadata['CLASS_INF']:
        for class_obj in metadata['CLASS_INF']['CLASS_OBJ']:
            print(f"\n分類: {class_obj['@name']}")
            
            # 各分類の項目を表示
            if 'CLASS' in class_obj:
                classes = class_obj['CLASS']
                if isinstance(classes, list):
                    for i, cls in enumerate(classes[:5]):  # 最初の5項目のみ表示
                        print(f"  - {cls['@name']} (コード: {cls['@code']})")
                    if len(classes) > 5:
                        print(f"  ... 他 {len(classes)-5} 項目")
                else:
                    print(f"  - {classes['@name']} (コード: {classes['@code']})")

# JSONファイルに保存して後で詳細に分析
with open('estat_metadata.json', 'w', encoding='utf-8') as f:
    json.dump(response_data, f, ensure_ascii=False, indent=4)

このコードを実行すると、統計表の構造や利用可能な分類項目(地域コード、時間コード、データ項目など)を確認できます。これにより、次のステップで実際のデータを取得する際に、必要な項目を正確に指定できるようになります。

2.1 カテゴリ情報の抽出と整理

メタ情報から特にカテゴリ情報(データの分類項目)を抽出して整理すると、データの構造をより理解しやすくなります。以下は、カテゴリ情報を抽出して整理するコードです:

# カテゴリ情報を格納する辞書
categories = {}

# APIレスポンスからカテゴリを抽出
meta_info = response_data
if "GET_META_INFO" in meta_info and "METADATA_INF" in meta_info["GET_META_INFO"]:
    metadata_inf = meta_info["GET_META_INFO"]["METADATA_INF"]
    
    # CLASS_INF(分類情報)
    if "CLASS_INF" in metadata_inf:
        class_inf = metadata_inf["CLASS_INF"]
        class_obj_list = class_inf.get("CLASS_OBJ", [])
        
        if not isinstance(class_obj_list, list):
            class_obj_list = [class_obj_list]
        
        # すべてのクラスオブジェクトを処理
        for class_obj in class_obj_list:
            class_name = class_obj.get("@name", "")
            class_code = class_obj.get("@id", "")  # @id を使用
            
            # カテゴリに関連するクラスを探す(cat01, cat02など)
            if class_code and class_code.startswith('cat'):
                classes = class_obj.get("CLASS", [])
                if not isinstance(classes, list):
                    classes = [classes]
                
                category_items = {}
                for cls in classes:
                    code = cls.get("@code", "")
                    name = cls.get("@name", "")
                    category_items[code] = name
                
                categories[class_code] = {
                    'name': class_name,
                    'items': category_items
                }

# カテゴリ一覧を表示
for cat_code, cat_info in categories.items():
    print(f"\n【{cat_code}: {cat_info['name']}】")
    for code, name in list(cat_info['items'].items())[:10]:  # 最初の10項目のみ表示
        print(f"  {code}: {name}")
    if len(cat_info['items']) > 10:
        print(f"  ... 他 {len(cat_info['items'])-10} 項目")

# カテゴリ情報をJSONファイルに保存
with open('estat_categories.json', 'w', encoding='utf-8') as f:
    json.dump(categories, f, ensure_ascii=False, indent=4)

このコードを実行すると、統計表に含まれるカテゴリ(例:人口区分、年齢区分、地域区分など)とそれぞれの項目が整理されて表示され、JSONファイルとしても保存されます。これにより、データ取得時に必要なカテゴリコードを正確に指定できるようになります。

3. 基本的なデータ取得

メタ情報を理解したら、次は実際の統計データを取得します。以下は、人口データを取得して整形するための関数の例です:

import requests
import pandas as pd
import json

def get_population_data(app_id):
    """
    e-Stat APIから人口データを取得する
    
    引数:
        app_id (str): e-Stat APIのアプリケーションID
        
    戻り値:
        pandas.DataFrame: フォーマットされた人口データ
    """
    # APIのベースURL
    api_url = "https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData"
    
    # リクエストパラメータ
    params = {
        "appId": app_id,           # アプリケーションID
        "statsDataId": "0000010101", # 人口統計ID
        "cdCat01": "A1101"         # 総人口のカテゴリコード
    }
    
    try:
        # HTTPリクエストを実行
        response = requests.get(api_url, params=params)
        
        # リクエストが成功したか確認
        response.raise_for_status()
        
        # JSONレスポンスをパース
        data = response.json()
        
        # APIがエラーを返したか確認
        result = data.get('GET_STATS_DATA', {}).get('RESULT', {})
        if result.get('STATUS') != 0:
            error_msg = result.get('ERROR_MSG', '不明なエラー')
            raise Exception(f"APIがエラーを返しました: {error_msg}")
        
        # 人口データを処理して返す
        return process_population_data(data)
        
    except requests.exceptions.RequestException as e:
        print(f"リクエスト中にエラーが発生しました: {e}")
        raise
    except Exception as e:
        print(f"データ処理中にエラーが発生しました: {e}")
        raise

def process_population_data(data):
    """
    人口データを処理してフォーマットする
    
    引数:
        data (dict): e-Stat APIからの生のJSONデータ
        
    戻り値:
        pandas.DataFrame: フォーマットされた人口データ
    """
    # 統計データを抽出
    statistical_data = data.get('GET_STATS_DATA', {}).get('STATISTICAL_DATA', {})
    
    if not statistical_data:
        raise Exception("レスポンスに統計データが見つかりません")
    
    # メタデータと実際のデータ値を抽出
    table_info = statistical_data.get('TABLE_INF', {})
    class_info = statistical_data.get('CLASS_INF', {})
    data_info = statistical_data.get('DATA_INF', {})
    
    # 人口データの値を抽出
    values = data_info.get('VALUE', [])
    if not isinstance(values, list):
        values = [values]
    
    # DataFrameのためのリストを作成
    records = []
    
    for item in values:
        area_code = item.get('@area')
        time_code = item.get('@time')
        value = float(item.get('$', 0))
        
        records.append({
            'area_code': area_code,
            'area_name': get_area_name(area_code, class_info),
            'time_code': time_code,
            'time_period': get_time_name(time_code, class_info),
            'population': value
        })
    
    # DataFrameを作成
    df = pd.DataFrame(records)
    
    # メタデータを属性として追加
    df.attrs['title'] = table_info.get('STATISTICS_NAME', '人口データ')
    df.attrs['source'] = table_info.get('STATISTICS_NAME', '')
    df.attrs['updated'] = table_info.get('UPDATED_DATE', '')
    
    return df

def get_area_name(area_code, class_info):
    """地域コードから地域名を取得する"""
    class_objs = class_info.get('CLASS_OBJ', [])
    if not isinstance(class_objs, list):
        class_objs = [class_objs]
    
    for obj in class_objs:
        if obj.get('@id') == 'area':
            classes = obj.get('CLASS', [])
            if not isinstance(classes, list):
                classes = [classes]
            
            for cls in classes:
                if cls.get('@code') == area_code:
                    return cls.get('@name', area_code)
    
    return area_code

def get_time_name(time_code, class_info):
    """時間コードから時間期間名を取得する"""
    class_objs = class_info.get('CLASS_OBJ', [])
    if not isinstance(class_objs, list):
        class_objs = [class_objs]
    
    for obj in class_objs:
        if obj.get('@id') == 'time':
            classes = obj.get('CLASS', [])
            if not isinstance(classes, list):
                classes = [classes]
            
            for cls in classes:
                if cls.get('@code') == time_code:
                    return cls.get('@name', time_code)
    
    return time_code

# 使用例
if __name__ == "__main__":
    app_id = "あなたのアプリケーションID"
    population_df = get_population_data(app_id)
    
    # 結果を表示
    print(f"取得したデータ: {len(population_df)}行")
    print("\n最新の人口データ (上位5件):")
    
    # 最新の年度のデータを抽出
    latest_year = population_df['time_period'].max()
    latest_data = population_df[population_df['time_period'] == latest_year].sort_values('population', ascending=False)
    
    print(latest_data.head(5)[['area_name', 'time_period', 'population']])
    
    # CSVファイルとして保存
    population_df.to_csv('population_data.csv', index=False, encoding='utf-8')
    print("\nデータをCSVファイルに保存しました: population_data.csv")

このコードは以下の処理を行います:

  1. get_population_data() 関数:e-Stat APIから人口データを取得します
  2. process_population_data() 関数:取得したデータを整形してDataFrameに変換します
  3. get_area_name()get_time_name() 関数:コードから名称を取得します
  4. 最後に、取得したデータの一部を表示し、CSVファイルとして保存します

このコードを実行すると、都道府県別の人口データが取得され、pandas DataFrameとして整形されます。これにより、データの分析や可視化が容易になります。

なお、APIリクエストでは以下のパラメータを指定しています:

  • statsDataId: 統計表ID(この例では人口・世帯に関する統計表)
  • cdCat01: カテゴリコード(この例では総人口を指定)

これらのパラメータは、前のステップで取得したメタ情報から適切な値を選択しています。

データの分析と可視化

取得したデータは様々な形で活用できます:

import matplotlib.pyplot as plt
import japanize_matplotlib  # 日本語フォント対応

# 取得したデータをDataFrameに変換する例
# (実際のレスポンス構造に合わせて調整が必要)

# グラフ作成例
plt.figure(figsize=(10, 6))
plt.bar(df['地域名'], df['人口数'])
plt.title('都道府県別人口')
plt.xlabel('都道府県')
plt.ylabel('人口(人)')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('population.png')
plt.show()

実践的なユースケース

1. 時系列データの分析

複数年のデータを取得して経年変化を分析できます:

# 複数年の統計データを取得する例
years = range(2015, 2023)
data_by_year = {}

for year in years:
    # APIパラメータを年ごとに変更
    params["cdTime"] = str(year)
    
    # データ取得処理
    # ...
    
    # 取得したデータを保存
    data_by_year[year] = result_data

# 年ごとの変化をグラフ化
plt.figure(figsize=(12, 6))
for year, data in data_by_year.items():
    plt.plot(data['区分'], data['値'], label=str(year))

plt.legend()
plt.title('年次推移')
plt.show()

2. 地域比較分析

地域ごとのデータを比較することも可能です:

# 都道府県コードを指定して地域別データを取得
prefecture_codes = ["01", "13", "27", "40"]  # 北海道、東京、大阪、福岡
data_by_prefecture = {}

for code in prefecture_codes:
    # APIパラメータを地域ごとに変更
    params["cdArea"] = code
    
    # データ取得処理
    # ...
    
    # 取得したデータを保存
    data_by_prefecture[code] = result_data

# 地域間比較をグラフ化
# ...

注意点と制限事項

  • APIの利用回数制限(標準アカウントで1日あたり50回まで)
  • 大量データ取得時のページング処理の必要性
  • データ形式(JSON/XML)の適切な指定
  • 統計表IDの正確な把握

まとめ

e-Stat APIを活用することで、日本の豊富な統計データに簡単にアクセスでき、データ分析やアプリケーション開発に役立てることができます。公式ドキュメントをしっかり確認し、必要なデータを効率的に取得・活用できるようになりましょう。

参考リンク