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});

85歳以上の死亡率が死亡数に比べて極端に高い。この世代が交通弱者であることを物語っていると思われる。

参考サイトhttps://stackoverflow.com/