Python:年齢別交通事故死亡数を死亡割合に変換する

pandasのdataframe内の各要素の値を、例えば、死亡者数から総数に対する割合を表わす百分率に変換するにはどうすればいいのだろうか?という非常に素朴な疑問が生じたので、鉄は熱いうちに打て、善は急げということで早速調べてみることにしました。

スポンサーリンク

データの下準備

先ず、このサイトから必要なデータを入手します。

from pandas import *

df = read_csv('caraccident.csv',encoding='shift_jis')
df.head(2)
表章項目 死因年次推移分類 性別 年齢(5歳階級) /時間軸(年次) 2017年 2016年 2015年 2014年 2010年 1995年 1990年 1985年 1980年 1975年 1970年 1965年 1960年 1955年 1950年
0 死亡数【人】 Hi15_交通事故 総数 総数 NaN 5004 5278 5646 5717 7222 15147 15828 14401 13302 16191 24096 19516 17757 10500 7542
1 死亡数【人】 Hi15_交通事故 総数 0〜4歳 NaN 30 31 40 31 53 194 293 332 565 996 1190 1139 1266 1108 1007

2 rows × 22 columns

df = df.set_index(['年齢(5歳階級)'])
df.drop(['表章項目','死因年次推移分類','性別','/時間軸(年次)'],axis=1,inplace=True)
df = df.apply(to_numeric, errors="coerce").astype(float)
df.head(2)
2017年 2016年 2015年 2014年 2010年 2005年 2000年 1995年 1990年 1985年 1980年 1975年 1970年 1965年 1960年 1955年 1950年
年齢(5歳階級)
総数 5004.0 5278.0 5646.0 5717.0 7222.0 10028.0 12857.0 15147.0 15828.0 14401.0 13302.0 16191.0 24096.0 19516.0 17757.0 10500.0 7542.0
0〜4歳 30.0 31.0 40.0 31.0 53.0 82.0 120.0 194.0 293.0 332.0 565.0 996.0 1190.0 1139.0 1266.0 1108.0 1007.0
スポンサーリンク

値を百分率に変換してプロットする

列の年数を抽出します。

years = df.filter(regex="\d{4}(?!\d)").columns.values
years = years.tolist()

各年数列の年齢(5歳階級)の値を合計してそれを分母にして年齢層別に割っていきます。

for i in (range(len(years))):
    df[years[i]][1:22]=df[years[i]][1:22]/df[years[i]][0]*100
from matplotlib.pyplot import *
from matplotlib.font_manager import FontProperties
from matplotlib import rcParams
style.use('ggplot')

fp = FontProperties(fname='/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf', size=54)
rcParams['font.family'] = fp.get_name()
rcParams["font.size"] = "20"
fig, ax = subplots(figsize=(25,12))
df[1:22].T.plot(kind='barh',ax=ax,stacked=True)
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5));
スポンサーリンク

年齢区分を若年、中年、高年、超高年に分ける

年齢区分を若年(0〜34歳)、中年(35歳〜59歳)、高年(60〜79歳)、超高年(80歳以上)の4つに分けて、交通事故死亡数を百分率に変換します。

df.reset_index(inplace=True)
df1 = df[:8][1:].groupby(np.arange(len(df[:8][1:]))//7).sum()
df1.index = df[:8][1:].loc[1::7, '年齢(5歳階級)']
df2 = df[:13][8:].groupby(np.arange(len(df[:13][8:]))//5).sum()
df2.index = df[:13][8:].loc[1::5, '年齢(5歳階級)']
df3 = df[:17][13:].groupby(np.arange(len(df[:17][13:]))//4).sum()
df3.index = df[:17][13:].loc[1::4, '年齢(5歳階級)']
df4 = df[:22][17:].groupby(np.arange(len(df[:22][17:]))//5).sum()
df4.index = df[:22][17:].loc[1::5, '年齢(5歳階級)']
df5 = concat([df1,df2,df3,df4], axis=0)
df5.rename(index={'0〜4歳':'0〜34歳','35〜39歳':'35〜59歳','60〜64歳':'60〜79歳','80〜84歳':'80歳〜'},inplace=True)
#df5.reset_index(inplace=True)
df5
2017年 2016年 2015年 2014年 2010年 2005年 2000年 1995年 1990年 1985年 1980年 1975年 1970年 1965年 1960年 1955年 1950年
年齢(5歳階級)
0〜34歳 677.0 802.0 822.0 887.0 1277.0 2210.0 3554.0 4820.0 6078.0 5552.0 5395.0 6983.0 10676.0 9395.0 9435.0 5768.0 4359.0
35〜59歳 1123.0 1127.0 1240.0 1238.0 1567.0 2602.0 3371.0 4041.0 4413.0 4691.0 4232.0 5100.0 7558.0 6246.0 5179.0 3141.0 2206.0
60〜79歳 1894.0 2021.0 2204.0 2272.0 2930.0 3790.0 4504.0 4816.0 4187.0 3369.0 3107.0 3598.0 5219.0 3435.0 2816.0 1452.0 886.0
80歳〜 1305.0 1328.0 1377.0 1319.0 1444.0 1416.0 1417.0 1450.0 1134.0 779.0 562.0 495.0 619.0 439.0 327.0 138.0 67.0
for i in (range(len(years))):
    df5[years[i]]=df5[years[i]]/df5[years[i]].sum()*100
from matplotlib.ticker import FuncFormatter

rcParams["font.size"] = "22"
fig, ax = subplots(figsize=(25,20))
df5.T.plot(kind='barh',ax=ax,stacked=True,alpha=1,width=.8)
ax,legend(bbox_to_anchor=(0,1.02,1,0.2),loc="lower left",mode="None",\
          borderaxespad=0,ncol=4,prop={'size': 26})
formatter = FuncFormatter(lambda y, pos: "%d%%" % (y))
ax.xaxis.set_major_formatter(formatter)
for p in ax.patches:
    left, bottom, width, height = p.get_bbox().bounds
    ax.annotate(str('{:.1f}'.format(width))+"%", xy=(left+width/2, bottom+height/2), 
                ha='center', va='center',size=25,color='w');

全体の何パーセントなのかでグラフ化した方が見やすいような気がします。2017年の60歳未満世代の死亡者数は、全交通事故死亡者数の36%でしかありません。これに対して1950年の事故の被害者は60歳未満世代が9割近かったことを考えると、こういった数字も日本の高齢化社会を象徴していると言えるかと思います。

スポンサーリンク

人口10万対死亡率と死亡数を比較する

先ず、上記のサイトからデータをダウンロードしてくる。

from pandas import *

df6 = read_csv('caraccidentdeath.csv',encoding='cp932')
df6.head(2)
表章項目 死因年次推移分類 性別 年齢(5歳階級) /時間軸(年次) 2017年 2016年 2015年 2014年 2010年 1995年 1990年 1985年 1980年 1975年 1970年 1965年 1960年 1955年 1950年
0 死亡率【人口10万対】 Hi15_交通事故 総数 総数 NaN 4.0 4.2 4.5 4.6 5.7 12.2 12.9 12.0 11.4 14.6 23.4 19.9 19.0 11.8 9.1
1 死亡率【人口10万対】 Hi15_交通事故 総数 0~4歳 NaN 0.6 0.6 0.8 0.6 1.0 3.3 4.5 4.5 6.7 10.0 13.6 14.0 16.1 12.0 9.0

2 rows × 22 columns

df6 = df6.set_index(['年齢(5歳階級)'])
df6.drop(['表章項目','死因年次推移分類','性別','/時間軸(年次)'],axis=1,inplace=True)
df6 = df6.apply(to_numeric, errors="coerce").astype(float)
df6.head(2)
2017年 2016年 2015年 2014年 2010年 2005年 2000年 1995年 1990年 1985年 1980年 1975年 1970年 1965年 1960年 1955年 1950年
年齢(5歳階級)
総数 4.0 4.2 4.5 4.6 5.7 7.9 10.2 12.2 12.9 12.0 11.4 14.6 23.4 19.9 19.0 11.8 9.1
0~4歳 0.6 0.6 0.8 0.6 1.0 1.5 2.0 3.3 4.5 4.5 6.7 10.0 13.6 14.0 16.1 12.0 9.0
df6.reset_index(inplace=True)
df.reset_index(inplace=True)

2017年の交通事故死亡数を100で割ってグラフを見やすくします。

from matplotlib.pyplot import *
from matplotlib.font_manager import FontProperties
from matplotlib import rcParams
import matplotlib.patches as mpatches
style.use('ggplot')

fp = FontProperties(fname='/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf', size=54)
rcParams['font.family'] = fp.get_name()
rcParams["font.size"] = "22"
a = mpatches.Patch(color='blue', label='死亡数')
b = mpatches.Patch(color='red', label='死亡率')
fig, ax = subplots(figsize=(25,20))
df[['年齢(5歳階級)','2017年']][1:23].set_index('年齢(5歳階級)').plot(kind='barh',\
   ax=ax,color='b')
df6[['年齢(5歳階級)','2017年']][1:23].set_index('年齢(5歳階級)').plot(kind='barh',\
   ax=ax,alpha=.5,color='r')
ax.legend(handles=[a,b],loc='upper right',fancybox=True,framealpha=0.5,prop={'size': 26});
参考サイトhttps://stackoverflow.com/

スポンサーリンク
スポンサーリンク