Pythonによるジニ係数の計算コード
内容
ジニ係数をPythonを使って計算します.よく知られた定義ではなく,簡略化された定義式を使うと計算が速くなる,という例を紹介します.
ジニ係数の直感的意味
ジニ係数は,所得や資産などの非負の資源分配の不平等度を測定する指標です.
たとえば,社会の全員に全く同じ量の富が分配されている場合にはジニ係数G
は0の値をとります.
y=[1,1,1,1,1,1] G(y)=0
もし,たった1人が, その社会に存在する全ての富を独占している状態だと,ジニ係数は1の値をとります.
y=[1,0,0,0,0,0] G(y)=0
つまり,ジニ係数は,完全に平等な状態であれば0,不平等が大きくなるほど1に近づく指標です.
ジニ係数の定義
よく知られたジニ係数の定義は 所得ベクトル に対して,
です(なおはの略です.はてぶろ上では2重和がうまく表示できないので省略しました).この定義を使った場合,最大数はです. 最大値をぴったり1にしたい場合は
を使います.ジニ係数の定義の直感的な意味は,「全てのペアの所得の差の絶対値を合計して,基準化した量」です. これを計算するPythonコードを考えてみましょう.定義通りにコードに翻訳すると,例えば次のような関数になるでしょう.
import statistics import math def gini(y): m = statistics.mean(y) n = len(y) a = 2*m*(n*(n-1)) ysum = 0 for i in range(n): for j in range(n): ysum = ysum +(math.fabs(y[i]-y[j])) return(ysum/a)
ためしに計算してみましょう.
y=[1,0,0,0,0,0] gini2(y) Out[ ]: 1.0 y=[1,1,1,1,1,1] gini2(y) Out[ ]: 0.0
完全不平等の場合に1,完全平等な場合に0をたしかに出力しています.
y=[1,2,3,4,5,6] gini2(y) Out[ ]: 0.3333333333333333
一様分布の場合は,約G=1/3
でした.
ところでジニ係数の定義を見て分かるとおり,所得ベクトル要素の差の絶対値を2重に足しています.は常に同じ値なので 計算としてはずいぶん無駄な作業をしています. 上記の工夫のないコードでも,データが少なければ特に問題は無いのですが,データが増えてくると若干計算速度が気になります.
たとえばrange( )
関数を使って,データを生成しながら計算してると,長さ2000くらいの短いリストでも出力までに時間がけっこうかかります.
import time #時間計測用 y=range(2000) start = time.time() [gini(y),time.time() - start] Out[ ]: [0.33366683341670833, 2.4708046913146973]
なんということだ!2.47秒もかかっている. これではシミュレーションでジニ係数を反復計算する際に面倒です.
ジニ係数の別の定義式
そこで,計算を早めるためにジニ係数の別の定義式を使います. 次の定義式は上述した式と同値であることが証明されています.ただしこの定義を用いる場合は,所得ベクトルを昇順に並び替える必要があります.
ただし
この式を使えば総和が2重になっている部分が簡略化されるので,ぐっと計算量が減ります.最大値を1にしたい場合は調整用にを掛けます.
上記の定義にもとづくコードは例えば以下のようなものになるでしょう.
#sortして計算の効率化 def gini2(y): y.sort() n = len(y) nume = 0 for i in range(n): nume = nume + (i+1)*y[i] deno = n*sum(y) return ((2*nume)/deno - (n+1)/(n))*(n/(n-1))
速くなったかどうか,確かめて見ましょう.
y=list(range(2000)) start = time.time() [gini3(y),time.time() - start] Out[9]: [0.3336668334167085, 0.0]
速くなりました!
以上です.