【ジニ指数をExcelとPythonで計算する】テスト結果を例にわかりやすく解説
日本は所得格差の小さな国といわれていましたが、2020年の調査では世界で14番目に所得格差の大きな国となっています。
世界のジニ係数 国別ランキング・推移|GLOBAL NOTE
この時によく使われる指標がジニ指数です。
このジニ指数は所得格差だけでなく、様々な格差の指標に使えます。
例えば群雄割拠で戦国時代のような業界では会社ごとの利益率に大きな違いはなくジニ指数が低くなる一方、寡占化の進んだ業界では大手とそれ以外で利益率に大きな差がありジニ指数が高くなることが予想されます。
このように色々なことに応用可能なジニ指数ですが、どのように計算されているのでしょうか?
考え方自体は難しくないのですが、計算には積分が必要になります。
でも大丈夫です。
本サイトで解説しているこちらの方法を使えば、積分だってExcelで計算できます。
フリーハンドの多角形の面積をExcelを使った2通りの方法で求めてみた。
もちろんPythonを使えばもっと簡単に計算できます。
今回はまずジニ指数を理解して、ExcelとPythonで計算できるようになることを目指します。
テスト結果を例にジニ指数を理解する
ジニ指数は言葉で理解しようとするより、図で理解する方が簡単です。
例として、ある塾のクラスのテスト結果の分布を見てみましょう。
このクラスの生徒10人のテスト結果は次の通りでした。
難しいテストですが一人だけ天才がいます。
このような場合はジニ指数が高くなることが予想されます。
点数の低い順に並べ替える
まずはこれを点数の低い順に並べ替えます。
ついでに合計値も求めておきます。
相対値に変える
次にこの点数を相対値に変えます。
何も難しいことはなくて、合計値(215)に対する各人の点数の割合を下記のように計算するだけです。
累積相対値を求める
次に相対値の累積を求めます。
これは次のようにして計算できます。
同様にして、人数の累積相対値も求めておきます。
このクラスには10人いるので、1人は全体の0.1です。
これを10人分積み上げると次のようになります。
グラフに描いてみる
次に累積相対点数をy軸、累積相対人数をx軸にして折れ線グラフにします。
この時、原点(0,0)を通るように、それぞれに0を加えておきます。
このように(0,0)を始点、(1,1)を終点とする右下に引っ張られた曲線になります。
ジニ指数とは、この右下に引っ張られる度合いを表す指数です。
そして、全く引っ張られていないグラフになる場合はジニ指数はゼロ、(1,1)まで完全に引っ張られているグラフになる場合はジニ指数は1になります。
ジニ指数を計算する
つまりジニ指数とは、下図で青色で影を付けた部分の大きさを0~1の数値で表したものです。
オレンジ色の直線(均等直線という)の下側の面積は0.5なので、
(0.5-下図で青色の影を付けた部分の面積)✕2
でジニ指数が計算できます。
またこの曲線はローレンツ曲線と呼ばれます。
そして青色の部分はローレンツ曲線の積分です。
つまりジニ指数は
(0.5-ローレンツ曲線の積分)✕2
で計算できます。
Excelでジニ指数を計算する
それではローレンツ曲線の積分をExcelで計算してみましょう。
積分をExcelで計算する方法はこちらの記事で解説しています。
【2通りの方法で!】あらゆる画像の面積をExcelで計算する方法をわかりやすく
台形に分ける方法と外積を使う方法の2通りありますが、今回の場合は下図のように1つの三角形(台形の一種)と9つの台形に分けられるため、台形に分ける方法で計算するのが簡単です。
台形の面積は(上辺+下辺)✕高さ÷2で計算できるので、次のように計算できます。
積分は0.243になりました。
従って、ジニ係数は(0.5-0.243)✕2=0.514となりました。
Pythonでジニ指数を計算する
次にこれをPythonで計算してみます。
まずはローレンツ曲線を描いてみましょう。
import numpy as np
import matplotlib.pyplot as plt
# 各生徒のスコアをnumpy配列に入れる
score = np.array([20, 25, 5, 5, 10, 100, 20, 15, 10, 5])
# 点数の低い順にソート
score = np.sort(score)
# 各生徒のスコアを相対値にする
rel_score = score / np.sum(score)
# 累積相対値にする ーーー1
rel_score_cum = rel_score.cumsum()
# numpy配列をリストに変換
rel_score_cum_list = rel_score_cum.tolist()
# リストの最初の要素に0を追加
rel_score_cum_list = [0] + rel_score_cum_list
# リストをnumpy配列に戻す
rel_score_cum = np.array(rel_score_cum_list)
# 人数の累積相対値を作る ーーー2
rel_x = np.linspace(0, 1, len(rel_score_cum))
# 1をy軸、2をx軸として折れ線グラフを描く
plt.plot(rel_x, rel_score_cum)
先程Excelで描いたのと同じローレンツ曲線のグラフができました。
後はscipyライブラリのintegrate.trapzを使ってローレンツ曲線を積分して、0.5から引いて2を掛けるだけです。
from scipy import integrate
# ローレンツ曲線の積分を計算
lorenz = integrate.trapz(rel_score_cum, rel_x)
# ローレンツ曲線の積分値からジニ指数を計算
gini = 2 * (0.5 -lorenz)
gini
----------------------------------
0.5139534883720931
このようにExcelで計算したのと同じ0.514になりました。
まとめ
このようにジニ指数はExcelでもPythonでも簡単に計算できます。
今回はデータ数が少なかったためPythonで計算する方が面倒な感じでしたが、次回は業界ごとのジニ指数を計算するのでPythonが威力を発揮します。
ところで世界のジニ係数 国別ランキング・推移|GLOBAL NOTEを見ましたか?
可処分所得で見たジニ指数ランキングですが、1位の南アフリカは0.62、2位のコスタリカは0.5です。
この塾のクラスのテスト結果のジニ指数と同じくらいです。
10人いて9人が25点以下で、1人だけ100点でしたね。
南アフリカやコスタリカは、これと同じくらいの極端な所得差があるということです。