統計検定、統計学入門 (基礎統計学Ⅰ) | 東京大学教養学部統計学教室 |本 | 通販 | Amazon に、
ジニ係数という、所得分配の不平等さを測る指標 が登場します。python でこのジニ係数の計算方法や、不平等差を測るための統計指標について調べてみましたので、結果を記載します。


不平等指標について


Wikipedia に記載されている不平等指標

python だと、ライブラリのパッケージ名に、inequalityつきます。
日本語だとあまり見つからなかったですが、英語版の Wikipedia にinequality metricsして以下のような指標が言及されています。

  • Gini index ジニ係数
    以下、ジニ係数 - Wikipedia引用です。

    社会における所得分配の不平等さを測る指標

  • 20:20 Ratio
    母集団の上位20%と、下位20%を比較して、そこにどれだけの格差があるのか示します。

  • Palma ratio パルマ比率
    パルマ比率。上位10%の所得合計÷下位40%の所得合計 で、低いほど格差が小さい指標になります。

  • Hoover index 集中指標
    地域的集中度の指標 です。 以下のpdfに説明が記載されています。
    研究シリーズ第32号

  • Coefficient of variation 変動係数 収入の分散の平方根を平均収入で割ったもの。統計で語られるそれは、収入に括ったものではないですが、経済指標としては、収入に括った値のようです。

  • Wage share 労働分配率
    企業において生産された付加価値全体のうちの、どれだけが労働者に還元されているかを示す割合。「人件費/付加価値」で算出された%で表されます。

  • Theil index タイル指数
    所得格差を示す指標。説明は、以下のpdfに記載されています。
    IPSJ-JNL5211001.pdf


その他の不平等指標

Wikipedia には記載がありませんが、その他の不平等指標として、以下があるようです。

  • Atkinson Index ダルトン・アトキンソン尺度
    所得格差を表す指標の一つで、所得が完全に平等に分配される状態にした時に社会が諦めねばならない総所得の割合 を示します。

  • Kakwani index カクワニ係数
    貧困を示す指標 ? ジニ係数と同じような値に思われました。


一般的に使用されている不平等指標

統計検定では、過去ジニ係数と、ローレンツ曲線についての出題があり、 一般的にも、それらがよく使われているようで、その他の指標についてはあまりWeb上の情報はないように見えました。

統計局ホームページ/統計Today No.53以下のように記載されています。

全国消費実態調査の結果や「経済財政白書」を見ると、ほぼ一貫して不平等の指標としてジニ係数が用いられています。政府統計では従来から平均値を単一指標として示すことが多く、不平等の指標についてもジニ係数を単一指標として示すことが多いです。不平等の指標としては、ピグー=ダルトン原理を満たすものとして、ジニ係数以外にもアトキンソン指標、一般化エントロピー、タイル指標など分割公理に対応した指標もありますが、国際的な比較の観点からもジニ係数が用いられているものと考えられています。


不平等指標の計算ができるライブラリについて

以下、見つかりました。
* pysal/pysal: PySAL: Python Spatial Analysis Library


pysal で不平等指標の計算をする

  • インストール

    python3 -m pip install pysal
    

  • ジニ係数
    空間ジニ係数 と ジニ係数を計算できます。

import pysal
import numpy as np

# pysalのデータセットに含まれる、メキシコの 32のメキシコの州、1940-2010年 10年ごと の時系列データを取得する
f=pysal.open(pysal.examples.get_path("mexico.csv"))
vnames=["pcgdp%d"%dec for dec in range(1940,2010,10)]
y=np.transpose(np.array([f.by_col[v] for v in vnames]))
regimes=np.array(f.by_col('hanson98'))

# 乱数を固定
np.random.seed(12345)

w = pysal.block_weights(regimes)
# 空間ジニ係数を求める
gs = pysal.inequality.gini.Gini_Spatial(y[:,0],w)
print("空間ジニ係数", gs.__dict__)


# ジニ係数を求める
gs = pysal.inequality.gini.Gini(y[:,0])
print("ジニ係数", gs.__dict__)

空間ジニ係数 {'g': 0.35372371173452849, 'wcg': 4353856.0, 'wg': 884130.0, 'dtotal': 5237986.0, 'den': 14808128.0, 'wcg_share': 0.29401798795904521, 'wcgp': array([ 4126228.,  4000994.,  4203292.,  4197086.,  4277902.,  4252922.,
        4039574.,  4089000.,  4290410.,  4120558.,  4195242.,  4209028.,
        4038750.,  4201308.,  4243490.,  4183814.,  4168974.,  4028010.,
        4363162.,  4110582.,  4181112.,  4335680.,  4240808.,  4154998.,
        4210238.,  4139444.,  4137668.,  4282600.,  4230824.,  4076498.,
        4183592.,  4206110.,  4029216.,  4236384.,  4110596.,  4038182.,
        4015358.,  4080044.,  4232460.,  4027460.,  4151414.,  4028410.,
        4206624.,  4183384.,  4194806.,  4188668.,  4242914.,  4281378.,
        4094012.,  4190744.,  4245344.,  4202794.,  4141048.,  4111328.,
        4126792.,  4332588.,  4328924.,  4264912.,  4172752.,  4145232.,
        4156490.,  4028624.,  4070424.,  4048800.,  4180720.,  4185870.,
        4140368.,  4325158.,  4172828.,  4283022.,  4032032.,  4064170.,
        4129126.,  4490908.,  4067802.,  4329386.,  4037278.,  4301716.,
        4177344.,  4296376.,  4108508.,  4094022.,  4084408.,  4228526.,
        4058830.,  4236482.,  4228552.,  4198926.,  4108536.,  4024064.,
        4152000.,  4146158.,  4045994.,  4139672.,  4199608.,  4124702.,
        4175594.,  4356900.,  4311728.]), 'p_sim': 0.040000000000000001, 'e_wcg': 4170356.7474747472, 's_wcg': 95869.167798782844, 'z_wcg': 1.9140590946861487, 'p_z_sim': 0.0278063026961195}
ジニ係数 {'g': 0.35372371173452849}

Gini_Spatial は、空間ジニ係数に関する値を、持ちつつ、gs.g ジニ係数が取得できます。
Gini は、ジニ係数のみを返し、gs.g ジニ係数が取得できます。

  • Theil指数
    pysal.inequality.theil.Theilpysal.inequality.theil.TheilDpysal.inequality.theil.TheilDSim用意されています。
    TheilDTheilDSimついては、理解が追いついておらず、ここでは、Theilついてのみ記載します。

import pysal
f=pysal.open(pysal.examples.get_path("mexico.csv"))
vnames=["pcgdp%d"%dec for dec in range(1940,2010,10)]
y=np.transpose(np.array([f.by_col[v] for v in vnames]))
theil_y=pysal.inequality.theil.Theil(y)
print(theil_y.T)

[ 0.20894344  0.15222451  0.10472941  0.10194725  0.09560113  0.10511256
  0.10660832]

IneqPy で不平等指標の計算をする

  • インストール

    python3 -m pip install git+https://github.com/mmngreco/IneqPy
    

  • ジニ係数を計算する
    ineqpy.giniジニ係数の計算が可能です。

import pandas as pd
import numpy as np
import ineqpy
from io import StringIO

data = StringIO("""index    renta   factor
0   -13004.12   1.0031
89900   141656.97   1.4145
179800  1400.38 4.4122
269700  415080.96   1.3295
359600  69165.22    1.3282
449500  9673.83 19.4605
539400  55057.72    1.2923
629300  -466.73 1.005
719200  3431.86 2.2861
809100  423.24  1.1552
899000  0   1.0048
988900  -344.41 1.0028
1078800 56254.09    1.2752
1168700 60543.33    2.0159
1258600 2041.7  2.7381
1348500 581.38  7.9426
1438400 55646.05    1.2818
1528300 0   1.0281
1618200 69650.24    1.2315
1708100 -2770.88    1.0035
1798000 4088.63 1.1256
1887900 0   1.0251
1977800 10662.63    28.0409
2067700 3281.95 1.167
""")

df = pd.read_table(data, index_col=0)
# dataframe のカラム名を指定する
print(ineqpy.gini(data=df, income='renta', weights='factor'))   

# 配列を指定する
print(ineqpy.gini(income=df.renta.values, weights=df.factor.values))

0.767391363659
0.767391363659

ineqpy の gini 関数は、何故かweights必須で指定する必要があります。
README.md Weighted Gini記載があるので、調整したジニ係数 で pysal計算できる値とは違うのかと思われます。

  • ダルトン・アトキンソン尺度
    ineqpy.atkinson で、ダルトン・アトキンソン尺度 の計算を行うことができます。

import pandas as pd
import numpy as np
import ineqpy
from io import StringIO

data = StringIO("""index    renta   factor
0   -13004.12   1.0031
89900   141656.97   1.4145
179800  1400.38 4.4122
269700  415080.96   1.3295
359600  69165.22    1.3282
449500  9673.83 19.4605
539400  55057.72    1.2923
629300  -466.73 1.005
719200  3431.86 2.2861
809100  423.24  1.1552
899000  0   1.0048
988900  -344.41 1.0028
1078800 56254.09    1.2752
1168700 60543.33    2.0159
1258600 2041.7  2.7381
1348500 581.38  7.9426
1438400 55646.05    1.2818
1528300 0   1.0281
1618200 69650.24    1.2315
1708100 -2770.88    1.0035
1798000 4088.63 1.1256
1887900 0   1.0251
1977800 10662.63    28.0409
2067700 3281.95 1.167
""")

df = pd.read_table(data, index_col=0)
# ダルトン・アトキンソン尺度 を計算   
print(ineqpy.atkinson(data=df, income='renta', weights='factor'))

0.42284127012
  • ローレンツ曲線
    ineqpy.lorenzローレンツ曲線を返すdataframeを取得できます。

import pandas as pd
import numpy as np
import ineqpy
from io import StringIO

data = StringIO("""index    renta   factor
0   -13004.12   1.0031
89900   141656.97   1.4145
179800  1400.38 4.4122
269700  415080.96   1.3295
359600  69165.22    1.3282
449500  9673.83 19.4605
539400  55057.72    1.2923
629300  -466.73 1.005
719200  3431.86 2.2861
809100  423.24  1.1552
899000  0   1.0048
988900  -344.41 1.0028
1078800 56254.09    1.2752
1168700 60543.33    2.0159
1258600 2041.7  2.7381
1348500 581.38  7.9426
1438400 55646.05    1.2818
1528300 0   1.0281
1618200 69650.24    1.2315
1708100 -2770.88    1.0035
1798000 4088.63 1.1256
1887900 0   1.0251
1977800 10662.63    28.0409
2067700 3281.95 1.167
""")

df = pd.read_table(data, index_col=0)
# ローレンツ曲線を示すデータフレームを取得
result = ineqpy.lorenz(data=df, income='renta', weights='factor')
%matplotlib inline
# x軸、y軸を指定してplot する    
result.plot(x='x', y='y')

<matplotlib.axes._subplots.AxesSubplot at 0x10fc60b00>

png

ローレンツ曲線と思われるグラフが描画できています。
元データがいまいちなんのデータなのかわからないので、あまり面白みはないかもしれません。


numpy でgini 係数を計算する

oliviaguest/gini: Calculate the Gini coefficient of a numpy array.記載のメソッドを拝借します。

import numpy as np   
def gini(array):
    """Calculate the Gini coefficient of a numpy array."""
    # based on bottom eq: http://www.statsdirect.com/help/content/image/stat0206_wmf.gif
    # from: http://www.statsdirect.com/help/default.htm#nonparametric_methods/gini.htm
    array = array.flatten() #all values are treated equally, arrays must be 1d
    if np.amin(array) < 0:
        array -= np.amin(array) #values cannot be negative
    array += 0.0000001 #values cannot be 0
    array = np.sort(array) #values must be sorted
    index = np.arange(1,array.shape[0]+1) #index per array element
    n = array.shape[0]#number of array elements
    return ((np.sum((2 * index - n  - 1) * array)) / (n * np.sum(array))) #Gini coefficient

import pysal
import numpy as np

# pysalのデータセットに含まれる、メキシコの 32のメキシコの州、1940-2010年 10年ごと の時系列データを取得する
f=pysal.open(pysal.examples.get_path("mexico.csv"))
vnames=["pcgdp%d"%dec for dec in range(1940,2010,10)]
y=np.transpose(np.array([f.by_col[v] for v in vnames]))
regimes=np.array(f.by_col('hanson98'))

# ジニ係数を求める
print("ジニ係数", gini(y[:,0]))

ジニ係数 0.35372371173

pysal.inequality.gini.Gini同様の結果が取得できます。


参考

参考にした記事のリンクになります。

以上です。

コメント