読者です 読者をやめる 読者になる 読者になる

e-Stat 統計資料の可視化

最近統計に興味がでてきたので、JSONの取り扱いとPandasの練習、それと後々のブログのネタのため、まずは統計資料の可視化(つまりグラフ化)にトライしてみようと思います。

データは政府の統計総合窓口(e-Stat)にあるものを使います。ここはAPIを通してデータを公開しているので、遊ぶにはもってこいです。 APIを使うにはユーザー登録をしてアプリケーションIDが必要です。登録は簡単なので省略します。 (参考 : 政府統計の総合窓口(e-Stat)のAPIを使ってみよう)

さて、目指すデータは給与の分布がわかるデータです。先に書いてしまうと、これは国税庁の調査結果で民間給与実態統計調査という名で公表されています。このブログを書いた時点では平成27年(2015年)の調査が最新でした。この統計のうち第3表 給与階級別の総括表の「累年比較(給与所得者数)」というのが欲しいデータです。

ちなみに、厚生労働省賃金構造基本統計調査というモノを出しています。統計手法や統計の切り口などが違うようです。

統計情報の取得

それでは、国税庁のデータをe-Statにある開発ガイドAPIの使い方を参考に取得、分析してみます。まず、開発ガイドにあるように「統計表情報」を取得して目的のデータのIDを調べてみましょう。

# -*- coding: utf-8 -*-
import requests
import json

APP_KEY = '***'
URL =  'http://api.e-stat.go.jp/rest/2.1/app/json/getStatsList'
keyword = '給与階級別の総括表'
payload = {'appId': APP_KEY, 'lang': 'J', 'searchKind': '1', 'openYears': '2015', 'searchWord': keyword}

r = requests.get(URL, params=payload)
jd = json.loads(r.text)
tbl_list = jd['GET_STATS_LIST']['DATALIST_INF']['TABLE_INF']

for t in tbl_list:
    print('---')
    for k, d in t.items():
        if k == '@id' or k == 'TITLE':
            print(k, ":", d)
---
@id : 0003067277
TITLE : {'@no': '00301', '$': '全国計表\u3000第3表\u3000給与階級別の総括表 1年を通じて勤務した給与所得者・1年未満勤続者 (2007年~)'}
---
@id : 0003045911
TITLE : {'@no': '00401', '$': '全国計表\u3000第4表\u3000事業所規模別及び給与階級別の総括表 (2007年~)'}
---
@id : 0003045913
TITLE : {'@no': '00601', '$': '全国計表\u3000第6表\u3000企業規模別及び給与階級別の総括表 合計 (2007年~)'}
---
@id : 0003091185
TITLE : {'@no': '00602', '$': '全国計表\u3000第6表\u3000企業規模別及び給与階級別の総括表 役員 (2012年~)'}
---
@id : 0003091186
TITLE : {'@no': '00603', '$': '全国計表\u3000第6表\u3000企業規模別及び給与階級別の総括表 正規 (2012年~)'}
---
@id : 0003091187
TITLE : {'@no': '00604', '$': '全国計表\u3000第6表\u3000企業規模別及び給与階級別の総括表 非正規 (2012年~)'}

結果をみてみると、欲しいデータ「給与階級別の総括表 1年を通じて勤務した給与所得者・1年未満勤続者」の@idは0003067277でした。このID番号が実データを取得するときのキーになります。

メタ情報の取得

実際のデータを取得する前に、メタ情報を取得しておきます。メタ情報は統計データの属性、コードの意味などを提供してくれます。統計データ取得APIの出力にも含めることができますが、メタ情報は先に単体で取得した方が全体の見通しが良さそうです。また、下の例だとJSONデータを整形していますが、XMLでパパッとみちゃったほうが手軽だと思います。結構パースが面倒だったので。

# -*- coding: utf-8 -*-
import requests
import json

APP_KEY = '***'
URL =  'http://api.e-stat.go.jp/rest/2.1/app/json/getMetaInfo'
STATID= '0003067277'  // 統計情報で対象にする@id '0003067277'を指定する。
payload = {'appId': APP_KEY, 'lang': 'J', 'statsDataId': STATID}


r = requests.get(URL, params=payload)
jd = json.loads(r.text)
meta_data = jd['GET_META_INFO']['METADATA_INF']['CLASS_INF']['CLASS_OBJ']

for md in meta_data:
    print("@id:", md['@id'],"@name:" ,md['@name'])
    class_info = md['CLASS']
    
    for ci in class_info:
        print(ci)
@id: tab @name: 表章項目
{'@code': '0100', '@name': '平均年齢', '@level': '', '@unit': '歳'}
{'@code': '0110', '@name': '平均勤続年数', '@level': '', '@unit': '年'}
{'@code': '0120', '@name': '給与所得者数', '@level': '', '@unit': '人'}
{'@code': '0130', '@name': '給料・手当(総額)', '@level': '', '@unit': '百万円'}
{'@code': '0140', '@name': '給料・手当(平均)', '@level': '', '@unit': '千円'}
{'@code': '0150', '@name': '賞与(総額)', '@level': '', '@unit': '百万円'}
{'@code': '0160', '@name': '賞与(平均)', '@level': '', '@unit': '千円'}
{'@code': '0170', '@name': '給与(総額)', '@level': '', '@unit': '百万円'}
{'@code': '0180', '@name': '給与(平均)', '@level': '', '@unit': '千円'}
@id: cat01 @name: 給与階級
{'@code': '1', '@parentCode': '15', '@name': '100万円以下', '@level': '2'}
{'@code': '2', '@parentCode': '15', '@name': '200万円以下', '@level': '2'}
{'@code': '3', '@parentCode': '15', '@name': '300万円以下', '@level': '2'}
{'@code': '4', '@parentCode': '15', '@name': '400万円以下', '@level': '2'}
{'@code': '5', '@parentCode': '15', '@name': '500万円以下', '@level': '2'}
{'@code': '6', '@parentCode': '15', '@name': '600万円以下', '@level': '2'}
{'@code': '7', '@parentCode': '15', '@name': '700万円以下', '@level': '2'}
{'@code': '8', '@parentCode': '15', '@name': '800万円以下', '@level': '2'}
{'@code': '9', '@parentCode': '15', '@name': '900万円以下', '@level': '2'}
{'@code': '10', '@parentCode': '15', '@name': '1,000万円以下', '@level': '2'}
{'@code': '11', '@parentCode': '15', '@name': '1,500万円以下', '@level': '2'}
{'@code': '12', '@parentCode': '15', '@name': '2,000万円以下', '@level': '2'}
{'@code': '13', '@parentCode': '15', '@name': '2,500万円以下', '@level': '2'}
{'@code': '14', '@parentCode': '15', '@name': '2,500万円超', '@level': '2'}
{'@code': '15', '@name': '計', '@level': '1'}
@id: cat02 @name: 性別
{'@code': '1', '@parentCode': '3', '@name': '男', '@level': '2'}
{'@code': '2', '@parentCode': '3', '@name': '女', '@level': '2'}
{'@code': '3', '@name': '計', '@level': '1'}
@id: cat03 @name: 勤続状況
{'@code': '1', '@name': '1年勤続者', '@level': '1'}
{'@code': '2', '@name': '1年未満勤続者', '@level': '1'}
@id: time @name: 年
{'@code': '2014000000', '@name': '2014年', '@level': '1'}
{'@code': '2013000000', '@name': '2013年', '@level': '1'}
{'@code': '2012000000', '@name': '2012年', '@level': '1'}
{'@code': '2011000000', '@name': '2011年', '@level': '1'}
{'@code': '2010000000', '@name': '2010年', '@level': '1'}
{'@code': '2009000000', '@name': '2009年', '@level': '1'}
{'@code': '2008000000', '@name': '2008年', '@level': '1'}
{'@code': '2007000000', '@name': '2007年', '@level': '1'}

メタデータをみると実データの絞り込みのヒントがありました。 もともとの統計データと見てみると、表章項目で必要なのは「給与所得者数」なので、@codeは120となります。 また、男女別、勤続状況が1年勤続者かどうか、というメタ情報もあるようです。ここでの@idは実データに含まれるコード情報と名称を紐付けるキーとなっているので出力しました。

実データの取得

さて、ようやく実データをとってみましょう。給与所得者数(@code = 0120)は複数条件で統計がとられていて量が多いので、まずは勤続年数を1年以上、性別は男女合計、2014年データに絞り込んで表示してみます。

# -*- coding: utf-8 -*-
import requests
import json

APP_KEY = '***'
URL =  'http://api.e-stat.go.jp/rest/2.1/app/json/getStatsData'
STATID= '0003067277'
payload = {'appId': APP_KEY, 'lang': 'J', 'statsDataId': STATID, 'metaGetFlg': 'N'}

r = requests.get(URL, params=payload)
jd = json.loads(r.text)
stat_data = jd['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE']
for v in stat_data:
// メタ情報と見比べて抽出条件を設定する。@tab, @cat02, @time, @cat03ともメタ情報に定義がある。
    if   v['@tab'] == '0120' and v['@cat02'] == '3' and v['@time'] == '2014000000' and v['@cat03']=='1' :
        print(v)
        
{'@cat02': '3', '$': '4177606', '@cat03': '1', '@tab': '0120', '@cat01': '1', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '7214336', '@cat03': '1', '@tab': '0120', '@cat01': '2', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '8028818', '@cat03': '1', '@tab': '0120', '@cat01': '3', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '8240812', '@cat03': '1', '@tab': '0120', '@cat01': '4', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '6632790', '@cat03': '1', '@tab': '0120', '@cat01': '5', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '4501863', '@cat03': '1', '@tab': '0120', '@cat01': '6', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '2804385', '@cat03': '1', '@tab': '0120', '@cat01': '7', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '1895962', '@cat03': '1', '@tab': '0120', '@cat01': '8', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '1249799', '@cat03': '1', '@tab': '0120', '@cat01': '9', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '821431', '@cat03': '1', '@tab': '0120', '@cat01': '10', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '1483416', '@cat03': '1', '@tab': '0120', '@cat01': '11', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '305993', '@cat03': '1', '@tab': '0120', '@cat01': '12', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '94661', '@cat03': '1', '@tab': '0120', '@cat01': '13', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '110800', '@cat03': '1', '@tab': '0120', '@cat01': '14', '@unit': '人', '@time': '2014000000'}
{'@cat02': '3', '$': '47562672', '@cat03': '1', '@tab': '0120', '@cat01': '15', '@unit': '人', '@time': '2014000000'}

データがとれましたので、次回はPandasで処理してみたいと思います。