日本の年収と分布を可視化する重要性
国税庁からサラリーマンなど民間企業で働く人の去年の平均年収が発表されました。 分布が偏っているにも関わらず概要として発表されニュースになるのが決まって「平均年収」なため、こうしたニュースが出ると毎年必ず「平均値ではなく中央値を見るべき(ちなみに中央値はもっと低い)」や「年収の分布を表示せよ」といった主張が (特に統計やデータ分析の界隈から) 聞こえてきます。
私も普段はデータ分析を生業としているため、上記のような平均値だけを見てものごとを判断するのは危険という方向性の主張には同意できます。少し文脈は異なりますが、私もデータの分布(バラつき)を捉えよ!アプリゲームを分析する上での観点 - YuRAN-HIKOという記事で分析の業務にかかわるにあたって代表値のみならずちゃんとデータの分布を見て判断することが大切であると書きました。
ただし、データの分布をヒストグラム等で可視化した際の弱点として、時系列の変化を捉えづらいといったことがあります。ヒストグラムは縦軸に度数、横軸に階級を取っているため、ある1時点(ないしは期間)におけるデータの分布を可視化することに向いていますが、そこに時系列変化の概念を持ち込もうとすると三次元の情報になるため、単純に1枚のグラフにして表すことが難しいためです*1。
もちろん、データの分布を捉える上でなにか1時点の状態だけを切り取って考えたいのであれば、普通にヒストグラム等で可視化すれば問題ないのですが、例えば過去からの推移の中で今の分布がどうなっているのかであったり、その推移を踏まえて今後どうなりそうなのかを予測する上では時系列の変化を上手く捉えられていたほうが有益ではあります。
そこで、本稿では python の matplotlib の機能を用いて動的なグラフを作成し、データの分布の変化を捉える方法について紹介したいと思います。用いるデータは上記の国税庁が出している「民間給与実態統計調査」で、これの2007年から2017年の10年分のデータを用いたいと思います*2。
ちなみに、本稿の目的はあくまでデータの分布の推移を動的に可視化することにあり、それに基づいて日本の年収分布そのものや経済に関して論じるものではありません。
日本の年収データの準備
データは上記の「民間給与実態統計調査」を基に CSV ファイルを作成し、それを用いることとします。元データがたくさんあって分かりづらいですが、左記調査の中の「第3表 給与階級別の総括表」から取っており、それを「調査対象年」「階級(=年収カテゴリ)」「相対度数(=その階級が給与所得者全体の何%を占めるか)」の3カラムからなるデータに変換しています。
puthon で年収分布を可視化するコードを記述
次に、上記のデータを python の matplotlib.animation ライブラリにある FuncAnimation 関数で動的に描画しようと思います。そして描画したグラフを GIF ファイルで出力することとします。
まずはライブラリのインポートから。
import math import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib import animation
次に、先ほどの CSV ファイルを読み込みます。
# 作成した income_dist.csv を読み込む data = pd.read_csv("income_dist.csv")
次が本記事の一番のキモの部分になります。FuncAnimation 関数を用いるときはあらかじめ _update 関数を定義してその中で毎フレームごとの描画内容を記述し、描画に関するパラメータを設定してそれを FuncAnimation 関数の引数に設定すれば OK です。最後にそれを GIF ファイルの形式で保存しています。
def _update(frames, left, height): # 今表示しているグラフを削除 plt.cla() # 当該年のデータを読み込む data_ex = data[data['year']==frames] left = data_ex['income'] height = data_ex['ratio'] # matplotlib.bar で棒グラフを描画 plt.bar(left, height) # グラフの細かい設定を調整 plt.title("Japan's Income Distribution: Year {}".format(frames)) plt.ylim(0, 0.2) plt.xlabel("income") plt.ylabel("ratio") def main(): # 描画サイズを設定 fig = plt.figure(figsize=(15,6)) # 描画するデータの配列を用意 left = [] height = [] # 描画に関連するパラメータを設定 params = { 'fig': fig, 'func': _update, 'fargs': (left, height), 'frames': np.arange(2007, 2018, 1), 'repeat': True, 'interval': 1000, } # matplotlib.animation の FuncAnimation を使って動的にグラフを描画 anime = animation.FuncAnimation(**params) # 描画したグラフを GIF ファイルで保存 anime.save('income_dist.gif', writer='pillow') if __name__ == '__main__': main()
年収分布の可視化
こちらが上記のコードで作成した GIF ファイルになります。ちょうどリーマンショックがあった 2008年の直後は分布がガクッと左側に寄り、高額所得者が減少して年収 400万円以下の層の割合が一時的に増加していますが、その後は多少年ごとの変動はあるものの、傾向として分布が右側 (=高額所得側) に寄ってきていることが分かるかなと思います。
Python で分布図の推移を可視化する
- python の matplotlib.animation.FuncAnimation を使うことで動的なグラフを描画することができる
- 上記の関数を使うことで、データの分布の「変化」ないしは「推移」を視覚的に捉えることができる
*1:ヒートマップで表現できるでしょうという突っ込みが入りそうですが......。確かにヒートマップで表現することはできるものの、個人的にはどうもヒートマップは情報が多くなるとみにくい感が否めず......。
*2:https://www.e-stat.go.jp/stat-search/files?page=1&layout=datalist&toukei=00351000&tstat=000001012969&cycle=7&year=20170&month=0&tclass1=000001012970&result_back=1