都道府県別の人口偏りを調査

こんにちは。
独学ですが、pythonと統計数学を勉強しています。

今回の記事はJupyter Notebookを使って、
統計検定2級の勉強目的をこめて、
出題範囲であるローレンツ曲線で、
都道府県別の人口の偏りを調査しました。

参考：[ローレンツ曲線　統計学の時間](https://bellcurve.jp/statistics/course/1664.html)



都道府県別の人口については、
以下のサイトを参考にCSVのデータを作成しました。
2018年10月時点のものです。

参考：[【都道府県】人口ランキング](https://uub.jp/rnk/p_k.html)



#環境#
Windows 7
anaconda 2018.12
python 3.7.1



#調査結果#
調査結果です。
Jupyter Notebookから画面出力したキャプチャを少し加工しています。


![ToDoFuKenQiita.png](https://qiita-image-store.s3.amazonaws.com/0/178806/cb989ab9-ac21-d76b-ec04-6662bf728971.png)


細かい数字がたくさん並んでいますね。


注目するべき点は、
都道府県別の累積相対度数（tdfkn_cumulative_relative_frequency）
人口の累積相対度数（ppltn_cumulative_relative_frequency）
の部分です。


都道府県別の累積相対度数：　0.19...
人口の累積相対度数：　　　　0.54...
また、
都道府県別の累積相対度数：　0.34...
人口の累積相対度数：　　　　0.69...
となっています。


これはどういうことかというと、
**約2割の都道府県に日本全体の人口の5割強が住んでいて、
約3割の都道府県に日本全体の人口の約7割が住んでいる。**
ということを示しています。

また、ローレンツ曲線は
全く偏りがなく完全に均等配分されている場合には、
```y = x```のグラフ（完全平等線）を描きます。

**グラフでは完全平等線に対して、下方へのズレが見られます。**

これらのことから、
都市部へ人口が大きく偏っていることが分かりますね。

#調査方法#
①まず、スタージェスの公式を使って階級の数を求めました。

```math
階級の数 = 1 + \log_2 n \\
(n=データ数)
```

n=47（都道府県の数）としたとき、
計算結果は6.55...となります。

今回は
階級の数：7
階級幅　：2,000,000
としています。

②次に、各階級ごとの都道府県数、人口の度数を集計。
　そこから、それぞれの相対度数、累積相対度数を算出します。

③そして、
X軸: 人口の累積相対度数
Y軸: 都道府県数の累積相対度数
にとったグラフがローレンツ曲線になります。

##ソースコード##
以下は、今回調査用に使った全ソースコードになります。

```python

%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import math


#定数
LF = '\n'
CSV_FILE = 'PopulationByToDoGFuKen.csv'
ENCODING_METHOD = 'cp932'


def read_csv():
    """
    csvの読込
    """
    output = pd.read_csv(CSV_FILE, encoding=ENCODING_METHOD)
    
    #出力
    print('★加工元CSVファイル★')
    print(str(output) + LF + LF)
    return output


def format_df(df):
    """
    DataFrameの加工
    """
    #度数の集計用のbool DataFrame
    df_1400 = df.query('12000000 <= population')
    df_1200 = df.query('10000000 <= population < 12000000')
    df_1000 = df.query('8000000 <= population < 10000000')
    df_0800 = df.query('6000000 <= population < 8000000')
    df_0600 = df.query('4000000 <= population < 6000000')
    df_0400 = df.query('2000000 <= population < 4000000')
    df_0200 = df.query('population < 2000000')
    
    #都道府県の度数のSeries
    tdfkn_frequency = pd.Series([
    len(df_1400.index)
    , len(df_1200.index)
    , len(df_1000.index)
    , len(df_0800.index)
    , len(df_0600.index)
    , len(df_0400.index)
    , len(df_0200.index)])
        
    #人口の度数のSeries
    ppltn_frequency = pd.Series([
    df_1400['population'].sum()
    , df_1200['population'].sum()
    , df_1000['population'].sum()
    , df_0800['population'].sum()
    , df_0600['population'].sum()
    , df_0400['population'].sum()
    , df_0200['population'].sum()])
     
    #相対度数のSeries
    tdfkn_relative_frequency = tdfkn_frequency / tdfkn_frequency.sum()
    ppltn_relative_frequency = ppltn_frequency / df['population'].sum()
    #float型へ変換
    tdfkn_relative_frequency = tdfkn_relative_frequency.astype(np.float64)
    ppltn_relative_frequency = ppltn_relative_frequency.astype(np.float64)
           
    #累積相対度数のSeries作成
    tdfkn_cumulative_relative_frequency = cumulative(tdfkn_relative_frequency)
    ppltn_cumulative_relative_frequency = cumulative(ppltn_relative_frequency)
  
    #DataFrame生成
    new_df = pd.DataFrame({
        'tdfkn_frequency': tdfkn_frequency
        , 'tdfkn_relative_frequency': tdfkn_relative_frequency
        , 'tdfkn_cumulative_relative_frequency': tdfkn_cumulative_relative_frequency
        , 'ppltn_frequency': ppltn_frequency
        , 'ppltn_relative_frequency': ppltn_relative_frequency
        , 'ppltn_cumulative_relative_frequency': ppltn_cumulative_relative_frequency
    })

    #出力
    print('★加工後DataFrame★')
    display(new_df)
    print(LF)
    return new_df


def cumulative(srs_relative_frequency):
    """
    累積相対度数Seriesの生成
    """   
    crf = 0
    #累積相対度数 列用のSeries
    srs_cumulative_relative_frequency = pd.Series([0, 0, 0, 0, 0, 0, 0]).astype(np.float64)
    
    #累積相対度数の集計
    for cnt, row in srs_relative_frequency.iteritems():
        crf += srs_relative_frequency[cnt]
        srs_cumulative_relative_frequency[cnt] = crf

    return srs_cumulative_relative_frequency
    

def sturges(input):
    """
    スタージェスの公式
    """
    output = 1 + math.log2(input)
    
    #出力
    print('★階級幅の算出★' )
    print(str(output) + LF)
    return output

                                                    
def show_lorenz(df):
    """
    ローレンツ曲線の表示
    """
    fig = plt.figure()
    ax1 = fig.add_subplot(1,1,1)
    
    #X軸: 人口の累積相対度数
    #Y軸: 都道府県数の累積相対度数
    ax1.plot(df['ppltn_cumulative_relative_frequency']
             , df['tdfkn_cumulative_relative_frequency'])
    
    #完全平等線
    x = np.linspace(0, 1, 10)
    y = x
    ax1.plot(x, y, linestyle=":")

    #垂直、平行線
    plt.hlines(0.19, 0, 0.54, "m", linestyle=":")
    plt.vlines(0.54, 0, 0.19, "m", linestyle=":")
    plt.hlines(0.34, 0, 0.69, "m", linestyle=":")
    plt.vlines(0.69, 0, 0.34, "m", linestyle=":")
        
    #グラフの範囲　設定
    ax1.set_xlim(0, 1)
    ax1.set_ylim(0, 1)
    
    #縦横比　１：１
    plt.axes().set_aspect('equal')

    plt.title("Lorenz-Curve")

    plt.xlabel("Population")
    plt.ylabel("ToDoFuKen")
       
    plt.show() 
    plt.savefig('PopulationByToDoFuKen.png')
    

def main():
    """
    メイン関数
    """
    #csv読み込み
    df = read_csv()
    
    #階級幅をスタージェスの公式より算出
    class_width = sturges(len(df.index))
    
    #DataFrame加工
    formated_df = format_df(df)
    
    #ローレンツ曲線の表示
    show_lorenz(formated_df)
    return 


#エントリポイント
main()
```