ExcelファイルをPythonでデータ分析する
1.Excelファイルの読み込み - 2.グラフ - 3.度数分布 - 4.ランキングチャート - 5.相関 - 6.ディシジョンツリー
「ExcelファイルをPythonでデータ分析する」は上のような一連の記事になっており、2~6までは事前に1.Excelファイルの読み込みと事前処理が行われていることを前提としています。
都道府県ごとの度数分布
ビン(ヒストグラムの棒)の大きさを自動で作る場合
1920年の都道府県ごとの人口について都道府県数を度数とした度数分布を作成してみます。x軸は都道府県の人口を10個のグループに分けたもので、y軸にはそのグループに属する都道府県の数とします。
以下はそのプログラムで、matplotlib.pyplot.subplotsでグラフ描画領域を作りmatplotlib.axes.histでヒストグラムを描画します。描画するデータは、全国のデータを除外した1920年の男女総数です。
import matplotlib.pyplot as plt
import japanize_matplotlib
import numpy as np
import math
# グラフ描画領域の生成
fig,ax = plt.subplots(figsize=(16,8))
# 都道府県からは全国を除外し、1920年の総数の人口データでヒストグラムを作成する。
# ビン(人口のグループ数)はデフォルトの10、その区切り方も自動としている。
n,bins,patches = ax.hist(df0.loc[filter(lambda l:"全国" not in l,df0.index),"1920年_総数"],rwidth=0.5)
# x軸の目盛りを付与する。
ax.set_xticks([(bins[i+1]+bins[i])/2 for i in range(len(bins)-1)])
# x軸目盛りのラベルを設定する。
ax.set_xticklabels([f"{bins[i]}-{bins[i+1]}" for i in range(len(bins)-1)],rotation=90)
# タイトル、x軸、y軸のラベル、グリッドを設定する。
ax.set_title(f"1920年の都道府県人口の度数分布 (ビンを自動で生成)")
ax.set_xlabel("人口")
ax.set_ylabel("都道府県数")
ax.grid(axis="y")
# グラフを描画する。
plt.show()
実行すると以下のようなヒストグラムが表示されます。
表示されたヒストグラムを見ると右側にある人口が吐出したところがあり、全体の傾向としては左よりつまり人口の少ない都道府県が多く一部の都道府県の人口のみが多いことが分かります。しかしx軸の数値は細かすぎてすこし分かりずらいところがあります。この点が自動でビンの大きさを決めることの問題点です。さらに例えばこの1920年以外の別の年のヒストグラムを表示して比較しようとしたときもx軸の細かすぎる数値は分かりにくいです。
ビンの大きさを指定する。
matplotlib.axes.histをそのまま使用すると人口のグループは自動的に形成されるのですが、ただしこのグループは人口の数値が切りの良い数値になることは少ないため、予めnumpy.histogram_bin_edgesによって切りの良い数字で区切られたグループを作成することにします。そしてそのグループのラベルを作成して、ラベルごとの度数分布をmatplotlib.axes.histによって作成します。
以下の図のように1つのビンの大きさから切りの良いビンの左端、右端を計算します。データの最大値または最小値をビンの単位で割って、最小値の場合は小数を切り捨て、最大値の場合は小数を切り上げするとビンの左または右端を求めることができます。
具体的には、ビンのサイズを50万人として、次のように計算できます。描画するときにビンの数(bins)とその幅(rng)を指定します。以下のプログラムはあくまでも実装例なので、上のプログラムに続いて実行してもエラーになりますのでご注意ください。
# ビンのサイズ(50万人)
bin_size = 500000
# ビンの左端と右端の計算(最小値をdata.min(), 最大値をdata.max()とする)
rng = (math.floor(data.min()/bin_size)*bin_size,
math.ceil(data.max()/bin_size)*bin_size)
# ビンの数
bins = int((rng[1]-rng[0])/bin_size)
# グラフの描画(dataはpandas.Series型の都道府県ごとの人口)
bin_edges = np.histogram_bin_edges(data,bins=bins,range=rng)
ビンの大きさを指定した1920年、1930年、1940年の人口比較
次のプログラムでは、1つのビンの大きさを100万人としてヒストグラムを作成します。また3つの時期を比べるためにまず1920年、1930年、1940年の3つからビンのビンの左端と右端を計算し同じ尺度で3か年を見てみます。
import matplotlib.pyplot as plt
import japanize_matplotlib
import numpy as np
import math
# "全国"という文字が入ったデータを除外して都道府県名一覧を作成する。
prefs = list(filter(lambda l:"全国" not in l,df0.index))
# 変化を観察する年
years = ["1920年_総数","1930年_総数","1940年_総数"]
# 区切りとする最小単位
bin_size = 1000000 # 100万
# 全国を抜いた都道府県の年ごとのデータを作成する。
data = df0.loc[prefs,years]
# 度数分布をキリの良い範囲で作るために最大値と最小値からビンを作成する。
# 都道府県の人口の最小値と最大値から、区切りの最小単位を使って切りの良い枠を作る。
rng = (math.floor(data.min().min()/bin_size)*bin_size,math.ceil(data.max().max()/bin_size)*bin_size)
bins = int((rng[1]-rng[0])/bin_size)
# 枠を指定して各ビン(度数分布の1つの箱)を作成する。
bin_edges = np.histogram_bin_edges(data,bins=bins,range=rng)
# 各ビンの名前を作成する。bin_edgesは最後のビンのみ 「~以上、~以下」でありそれ以外は「~以上、~未満」という文字を作成する。
xlabels = [f"{bin_edges[i]/10000}万以上 {bin_edges[i+1]/10000}万{'以下' if i==len(bin_edges)-2 else '未満'}" for i in range(len(bin_edges)-1)]
# 年ごとにヒストグラムを作成する。
for year in years:
# 指定された年の都道府県ごとの人口を取得する。
data = df0.loc[prefs,year]
# 図の領域を作成する。
fig,ax = plt.subplots(figsize=(16,8))
# ヒストグラムを描画する。先に準備しておいたbinを使用する。
r = ax.hist(data,rwidth=0.5,bins=bin_edges)
# x軸の軸目盛をbin_edgesの幅の平均値で作成する。
ax.set_xticks([(bin_edges[i+1]+bin_edges[i])/2 for i in range(len(xlabels))])
# x軸の軸目盛を設定する。
ax.set_xticklabels(xlabels,rotation=90)
# タイトルを設定する。
ax.set_title(f"{year}の都道府県人口の度数分布")
# x軸、y軸の軸ラベルを設定する。
ax.set_xlabel("人口によるグループ")
ax.set_ylabel("都道府県数")
# グリッドを表示する。
ax.grid(axis="y")
plt.show()
# 各ビンに入っている都道府県を一覧として作成する。
members = [[] for i in range(len(bin_edges)-1)]
for pref,value in data.items():
for i,e in enumerate(np.flipud(bin_edges[:-1])):
if value >= e:
members[len(xlabels)-i-1].append((pref,value))
break
pass
print(f"{year}の各ビンにある都道府県名")
for bin,pfs in zip(xlabels,members):
print(bin,pfs)
実行すると1920年、1930年、1940年のヒストグラムが次のように表示されます。
作成した3つのヒストグラムを比較すると、まずグラフの左端の100万人未満のグループは減少し、そして1920年では他の年に比べて比較的ひと塊となっていた人口分布が1930年、1940年と徐々に広がっていることが分かります。そして1940年では300万以上400万未満に小さな1つの山が形成され、全体として2こぶのグラフになっているようにも見えます。この記事の最初に示したビンの大きさを自動で求める方法でもその傾向は示されていますが、この100万人単位でのグラフでも人口集中県とそうではないところの2分化が始まっていると見ることができるかもしれません。
ヒストグラムに所属するデータを表示する
ヒストグラムの各ビンに所属するデータを表示します。以下のプログラムは、上のプログラムでも使用されているもので、年を指定してヒストグラムに入る都道府県名一覧を表示するものです。year変数に、例えば "1940年_総数" を入れると1940年のデータが表示されます。
# 調べる年を指定する
year = "1920年_総数"
# データの抽出
data = df0.loc[prefs,year]
# 各ビンに入っている都道府県を一覧として作成する。
members = [[] for i in range(len(bin_edges)-1)]
for pref,value in data.items():
for i,e in enumerate(np.flipud(bin_edges[:-1])):
if value >= e:
members[len(xlabels)-i-1].append((pref,value))
break
pass
print(f"{year}の各ビンにある都道府県名")
for bin,pfs in zip(xlabels,members):
print(bin,pfs)
以下は1920年のヒストグラムの各ビンに属する都道府県名です。
1920年_総数の各ビンにある都道府県名
0.0万以上 100.0万未満 [('青森県', 756454), ('岩手県', 845540), ('宮城県', 961768), ('秋田県', 898537), ('山形県', 968925), ('富山県', 724276), ('石川県', 747360), ('福井県', 599155), ('山梨県', 583453), ('滋賀県', 651050), ('奈良県', 564607), ('和歌山県', 750411), ('鳥取県', 454675), ('島根県', 714712), ('徳島県', 670212), ('香川県', 677852), ('高知県', 670895), ('佐賀県', 673895), ('大分県', 860282), ('宮崎県', 651097), ('沖縄県', 571572)]
100.0万以上 200.0万未満 [('福島県', 1362750), ('茨城県', 1350400), ('栃木県', 1046479), ('群馬県', 1052610), ('埼玉県', 1319533), ('千葉県', 1336155), ('神奈川県', 1323390), ('新潟県', 1776474), ('長野県', 1562722), ('岐阜県', 1070407), ('静岡県', 1550387), ('三重県', 1069270), ('京都府', 1287147), ('岡山県', 1217698), ('広島県', 1541905), ('山口県', 1041013), ('愛媛県', 1046720), ('長崎県', 1136182), ('熊本県', 1233233), ('鹿児島県', 1415582)]
200.0万以上 300.0万未満 [('北海道', 2359183), ('愛知県', 2089762), ('大阪府', 2587847), ('兵庫県', 2301799), ('福岡県', 2188249)]
300.0万以上 400.0万未満 [('東京都', 3699428)]
400.0万以上 500.0万未満 []
500.0万以上 600.0万未満 []
600.0万以上 700.0万未満 []
700.0万以上 800.0万以下 []
以下は1930年のヒストグラムの各ビンに属する都道府県名です。
1930年_総数の各ビンにある都道府県名
0.0万以上 100.0万未満 [('青森県', 879914), ('岩手県', 975771), ('秋田県', 987706), ('富山県', 778953), ('石川県', 756835), ('福井県', 618144), ('山梨県', 631042), ('滋賀県', 691631), ('奈良県', 596225), ('和歌山県', 830748), ('鳥取県', 489266), ('島根県', 739507), ('徳島県', 716544), ('香川県', 732816), ('高知県', 718152), ('佐賀県', 691565), ('大分県', 945771), ('宮崎県', 760467), ('沖縄県', 577509)]
100.0万以上 200.0万未満 [('宮城県', 1142784), ('山形県', 1080034), ('福島県', 1508150), ('茨城県', 1487097), ('栃木県', 1141737), ('群馬県', 1186080), ('埼玉県', 1459172), ('千葉県', 1470121), ('神奈川県', 1619606), ('新潟県', 1933326), ('長野県', 1717118), ('岐阜県', 1178405), ('静岡県', 1797805), ('三重県', 1157407), ('京都府', 1552832), ('岡山県', 1283962), ('広島県', 1692136), ('山口県', 1135637), ('愛媛県', 1142122), ('長崎県', 1233362), ('熊本県', 1353993), ('鹿児島県', 1556690)]
200.0万以上 300.0万未満 [('北海道', 2812335), ('愛知県', 2567413), ('兵庫県', 2646301), ('福岡県', 2527119)]
300.0万以上 400.0万未満 [('大阪府', 3540017)]
400.0万以上 500.0万未満 []
500.0万以上 600.0万未満 [('東京都', 5408678)]
600.0万以上 700.0万未満 []
700.0万以上 800.0万以下 []
最後に1940年のヒストグラムの各ビンに属する都道府県名です。
1940年_総数の各ビンにある都道府県名
0.0万以上 100.0万未満 [('富山県', 822569), ('石川県', 757676), ('福井県', 643904), ('山梨県', 663026), ('滋賀県', 703679), ('奈良県', 620509), ('和歌山県', 865074), ('鳥取県', 484390), ('島根県', 740940), ('徳島県', 718717), ('香川県', 730394), ('高知県', 709286), ('佐賀県', 701517), ('大分県', 972975), ('宮崎県', 840357), ('沖縄県', 574579)]
100.0万以上 200.0万未満 [('青森県', 1000509), ('岩手県', 1095793), ('宮城県', 1271238), ('秋田県', 1052275), ('山形県', 1119338), ('福島県', 1625521), ('茨城県', 1620000), ('栃木県', 1206657), ('群馬県', 1299027), ('埼玉県', 1608039), ('千葉県', 1588425), ('長野県', 1710729), ('岐阜県', 1265024), ('三重県', 1198783), ('京都府', 1729993), ('岡山県', 1329358), ('広島県', 1869504), ('山口県', 1294242), ('愛媛県', 1178705), ('長崎県', 1370063), ('熊本県', 1368179), ('鹿児島県', 1589467)]
200.0万以上 300.0万未満 [('神奈川県', 2188974), ('新潟県', 2064402), ('静岡県', 2017860)]
300.0万以上 400.0万未満 [('北海道', 3272718), ('愛知県', 3166592), ('兵庫県', 3221232), ('福岡県', 3094132)]
400.0万以上 500.0万未満 [('大阪府', 4792966)]
500.0万以上 600.0万未満 []
600.0万以上 700.0万未満 []
700.0万以上 800.0万以下 [('東京都', 7354971)]
1940年で吐出した都道府県は東京都であることが分かります。