Plotly ExpressのSunburst(サンバーストチャート)で人口データを可視化する
ここでは、Plotly Expressのサンバーストチャートで人口データを可視化します。
### 2: sunburst chart
### 2-1: population by region, prefecture
df = raw_df.copy()
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口"
)
fig.show()
# %%
### 2-2: population ages over 65
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over65',
hover_name='prefecture_jp',
color='pop_over65',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over65='高齢者',
pop_sum='総人口',
pop_over65_sum='高齢者',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over65'): 高齢者人口 (65歳以上)"
)
fig.show()
# %%
### 2-3: population ages over 75
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over75',
hover_name='prefecture_jp',
color='pop_over75',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over75='高齢者',
pop_sum='総人口',
pop_over75_sum='高齢者',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over75'): 高齢者人口 (75歳以上)"
)
fig.show()
# %%
### 2-4: population ratio ages over 65
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over65_ratio',
hover_name='prefecture_jp',
color='pop_over65_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over65_ratio='高齢化率',
pop_sum='総人口',
pop_over65_ratio_sum='高齢化率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over65_ratio'): 高齢化率 (65歳以上)"
)
fig.show()
# %%
### 2-5: population ratio ages over 75
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over75_ratio',
hover_name='prefecture_jp',
color='pop_over75_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over75_ratio='高齢化率',
pop_sum='総人口',
pop_over75_ratio_sum='高齢化率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over75_ratio'): 高齢化率 (75歳以上)"
)
fig.show()
# %%
### 2-6: population ratio ages under 15
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_under15_ratio',
hover_name='prefecture_jp',
color='pop_under15_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_under15_ratio='少子化率',
pop_sum='総人口',
pop_under15_ratio_sum='少子化率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_under15_ratio'): 少子化率(15歳未満)"
)
fig.show()
# %%
### 2-7: population ratio adult (15~64)
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_adult_ratio',
hover_name='prefecture_jp',
color='pop_adult_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_adult_ratio='就業人口率',
pop_sum='総人口',
pop_adult_ratio_sum='就業人口率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_adult_ratio'): 就業人口率(15~64歳)"
)
fig.show()
# %%
図5-1では、地方、都道府県ごとの人口比率を円グラフで表示しています。
内側の円には、地方の人口比率が表示されています。
外側の円には、都道府県国ごとの人口比率が表示されています。
このグラフからは、地方と都道府県ごとの人口比率が同時に可視化できます。
図5-2では、前出(図5-1)の内側の円から「関東地方」をクリックして関東地方の都道府県の人口を表示させています。
ここでは、東京都にマウスをホバリングさせてホバーテキストを表示させています。
図5-3では、前出(図5-1)の内側の「中部地方」にマウスをホバリングさせてホバーテキストを表示させています。
ホバーテキストには、中部地方の「総人口(21,010,000)」が表示されます。
図5-4では、65歳以上の高齢者の人口をグラフに表示しています。
図5-5では、75歳以上の高齢者の人口をグラフに表示しています。
図5-6では、65歳以上の住民を対象にした高齢化率(%)をグラフに表示しています。
このグラフからは、秋田県がもっとも高齢化がすすんでいることが分かります。
図5-7では、前出(図5-6)の「秋田県」にマウスをホバリングさせてホバーテキストを表示させています。
秋田県の高齢化率は「37.99%」になっています。
図5-8では、75歳以上の住民を対象にした高齢化率(%)を表示しています。
ここでは、高齢化率が低い沖縄県にマウスをホバリングさせてホバーテキストを表示させています。
沖縄県の高齢化率は「10.62%」になっています。
図5-9では、15歳未満の住民を対象にした少子化率(%)をグラフに表示しています。
少子化率の場合、数値が高いほど少子化率がすすんでいないことを意味します。
ここでは、少子化がすすんでいない沖縄県にマウスをホバリングさせてホバーテキストを表示させています。
沖縄県の少子化率は「16.54%」になっています。
図5-10では、少子化がすすんでいる秋田県にマウスをホバリングさせてホバーテキストを表示させています。
秋田県の少子化率は「9.52%」になっています。
図5-11では、15歳~64歳までの住民(就業人口)を対象にしたグラフを表示しています。
ここでは、東京都にマウスをホバリングさせてホバーテキストを表示させています。
東京都の就業人口率は「66.06%」になっています。
Plotly ExpressのPie Chart(円グラフ)で人口データを可視化する
ここでは、Plotly Expressの円グラフで人口データを可視化します。
なお、65歳以上の人口の内訳についてはサンバーストチャートを使用します。
### 3: pie chart
### 3-0: japan
df = raw_df.copy()
df['region'] = 'Japan'
# Group the "df" DataFrame by "region",
# summing the 'pop_under15', 'pop_adult', 'pop_over65' columns, and reset the index
grp_df = df.groupby('region')[['pop_under15', 'pop_adult', 'pop_over65']].sum().reset_index()
melted_df = pd.melt(grp_df,
id_vars=['region'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
height=600,
labels=dict(
category='分類',
value='人口'
),
title="px.pie(names='category', values='value'): 全国 (人口構成)"
)
fig.show()
# %%
### 3-0-1: add a holl and annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
category='分類',
value='人口'
),
title='px.pie(hole=0.4): 全国 (人口構成)'
)
fig.update_layout(
annotations=[dict(text='全国', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-0-2: add a pull
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
category='分類',
value='人口'
),
title='px.pie() + update_traces(pull=[0, 0, 0.2]): 全国 (人口構成)'
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='全国', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-0-3: sunburst()
df = raw_df.copy()
df['region'] = 'Japan'
# Group the "df" DataFrame by "region",
# summing the 'pop_under15', 'pop_adult', 'pop_over65', 'pop_over75' columns, and reset the index
grp_df = df.groupby('region')[['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75']].sum().reset_index()
melted_df = pd.melt(grp_df,
id_vars=['region'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
melted2_df['region'] = '全国'
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
fig = px.sunburst(melted2_df,
path=['region', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['region', 'category', 'sub_category']): 全国 (人口構成)"
)
fig.show()
# %%
### 3-1: Tokyo
df = raw_df.copy()
df = df.query("prefecture_en == 'Tokyo'")
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
### 3-1-1: add a holl + pull + annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.pie(names='category', values='value'): 東京都 (人口構成)"
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='東京都', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-1-2: sunburst()
df = raw_df.copy()
df = df.query("prefecture_en == 'Tokyo'")
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
fig = px.sunburst(melted2_df,
path=['prefecture_jp', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['prefecture_jp', 'category', 'sub_category']): 東京都 (人口構成)"
)
fig.show()
# %%
### 3-2: Akita
df = raw_df.copy()
df = df.query("prefecture_en == 'Akita'")
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
### 3-2-1: add a holl + pull + annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.pie(names='category', values='value'): 秋田県 (人口構成)"
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='秋田県', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-2-2: sunburst()
df = raw_df.copy()
df = df.query("prefecture_en == 'Akita'")
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
fig = px.sunburst(melted2_df,
path=['prefecture_jp', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['prefecture_jp', 'category', 'sub_category']): 秋田県 (人口構成)"
)
fig.show()
# %%
### 3-3: okinawa
df = raw_df.copy()
df = df.query("prefecture_en == 'Okinawa'")
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
### 3-3-1: add a hole + pull + annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.pie(names='category', values='value'): 沖縄県 (人口構成)"
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='沖縄県', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-3-2: sunburst()
df = raw_df.copy()
df = df.query("prefecture_en == 'Okinawa'")
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
fig = px.sunburst(melted2_df,
path=['prefecture_jp', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['prefecture_jp', 'category', 'sub_category']): 沖縄県 (人口構成)"
)
fig.show()
# %%
図6-1では、日本(全国)の人口を3つの年齢区分(15歳未満、15歳~64歳、65歳以上)でグラフ化しています。
15歳~64歳の人口がもっとも多く「59.4%」になっています。
65歳以上の人口は「28.9%」、15歳未満の人口は「11.8%」となっています。
このグラフからは、日本の少子化がかなりすすんでいることが分かります。
図6-2では、Plotly Expressの「pie()」メソッドの引数に
「hole=0.4」を追加してドーナツ型の円グラフを作成しています。
内側の円には、figureクラスの「update_layout()」メソッドで注釈「全国」を表示させています。
図6-3では、figureクラス「update_traces()」メソッドで
「65歳」以上の円弧を引き出して強調させています。
図6-4では、Plotly Expressの「sunburst()」メソッドで
「65歳以上」の人口を更に「65歳~74歳」と「75歳以上」に分けています。
ここでは、「65歳~74歳」にマウスをホバリングさせてホバーテキストを表示させています。
図6-5では、東京都の円グラフを表示しています。
ここでは、「65歳以上」にマウスをホバリングさせてホバーテキストを表示させています。
ホバーテキストには、65歳以上の人口が表示されています。
図6-6では、Plotly Expressの「sunburst()」メソッドで東京都の
「65歳以上」の人口を更に「65歳~74歳」と「75歳以上」に分けています。
ここでは、「65歳~74歳」にマウスをホバリングさせてホバーテキストを表示させています。
図6-7では、秋田県の円グラフを表示しています。
ここでは、「65歳以上」にマウスをホバリングさせてホバーテキストを表示させています。
ホバーテキストには、65歳以上の人口が表示されています。
図6-8では、Plotly Expressの「sunburst()」メソッドで秋田県の
「65歳以上」の人口を更に「65歳~74歳」と「75歳以上」に分けています。
ここでは、「65歳~74歳」にマウスをホバリングさせてホバーテキストを表示させています。
図6-9では、沖縄県の円グラフを表示しています。
ここでは、「65歳以上」にマウスをホバリングさせてホバーテキストを表示させています。
ホバーテキストには、65歳以上の人口が表示されています。
図6-10では、Plotly Expressの「sunburst()」メソッドで沖縄県の
「65歳以上」の人口を更に「65歳~74歳」と「75歳以上」に分けています。
ここでは、「65歳~74歳」にマウスをホバリングさせてホバーテキストを表示させています。
全てのコードを掲載
ここでは、本記事で解説している全てのコードを掲載しています。
リスト8-1: Article152.py
# Analysis of population by prefecture and age in 2021 v30.py
'''
references
https://www.stat.go.jp/data/jinsui/2021np/index.html
https://plotly.com/python/sunburst-charts/
'''
# %%
import json
import urllib.request
import numpy as np
import math
import pandas as pd
import plotly.io as pio
import plotly.express as px
import plotly.graph_objects as go
# %%
### 0: prepare data
# 0-1: read a population data from a csv file
csv_file = r'https://money-or-ikigai.com/Menu/Python/Article/data/map/japan_population_by_prefecture_age(2021).csv'
# csv_file = 'datasets/csv/japan_population_by_prefecture_age(2021).csv'
df = pd.read_csv(csv_file)
# df.info()
# df
# %%
### 0-2: clean up data
pd.options.mode.chained_assignment = None
df['prefecture_jp'] = df['prefecture_jp'].apply(lambda x: x.replace(' ',''))
df['prefecture_jp'] = df['prefecture_jp'].apply(lambda x: x.replace(' ',''))
# df['male_under15'] = df['male_under15'].apply(lambda x: int(x))
df['male_adult'] = df['male_adult'].apply(lambda x: int(x.replace(',','')))
df['male_over65'] = df['male_over65'].apply(lambda x: int(x.replace(',','')))
# df['male_over75'] = df['male_over75'].apply(lambda x: int(x))
# df['female_under15'] = df['female_under15'].apply(lambda x: int(x))
df['female_adult'] = df['female_adult'].apply(lambda x: int(x.replace(',','')))
df['female_over65'] = df['female_over65'].apply(lambda x: int(x.replace(',','')))
df['female_over75'] = df['female_over75'].apply(lambda x: int(x.replace(',','')))
dfx = df[['prefecture_jp','male_under15','male_adult','male_over65','male_over75','female_under15','female_adult','female_over65','female_over75']]
# dfx.info()
# dfx.isnull().sum()
# %%
### 0-3: add the columns
dfx['male_under15'] = dfx['male_under15'].apply(lambda x: x * 1000)
dfx['male_adult'] = dfx['male_adult'].apply(lambda x: x * 1000)
dfx['male_over65'] = dfx['male_over65'].apply(lambda x: x * 1000)
dfx['male_over75'] = dfx['male_over75'].apply(lambda x: x * 1000)
dfx['female_under15'] = dfx['female_under15'].apply(lambda x: x * 1000)
dfx['female_adult'] = dfx['female_adult'].apply(lambda x: x * 1000)
dfx['female_over65'] = dfx['female_over65'].apply(lambda x: x * 1000)
dfx['female_over75'] = dfx['female_over75'].apply(lambda x: x * 1000)
dfx['pop_under15'] = dfx.apply(lambda row: row['male_under15'] + row['female_under15'], axis=1)
dfx['pop_adult'] = dfx.apply(lambda row: row['male_adult'] + row['female_adult'], axis=1)
dfx['pop_over65'] = dfx.apply(lambda row: row['male_over65'] + row['female_over65'], axis=1)
dfx['pop_over75'] = dfx.apply(lambda row: row['male_over75'] + row['female_over75'], axis=1)
dfx['pop_male'] = dfx.apply(lambda row: row['male_under15'] + row['male_adult'] + row['male_over65'], axis=1)
dfx['pop_female'] = dfx.apply(lambda row: row['female_under15'] + row['female_adult'] + row['female_over65'], axis=1)
dfx['pop'] = dfx.apply(lambda row: row['pop_male'] + row['pop_female'], axis=1)
dfx['pop_under15_ratio'] = dfx.apply(lambda row: round((row['pop_under15'] / row['pop']) * 100, 2), axis=1)
dfx['pop_adult_ratio'] = dfx.apply(lambda row: round((row['pop_adult'] / row['pop']) * 100, 2), axis=1)
dfx['pop_over65_ratio'] = dfx.apply(lambda row: round((row['pop_over65'] / row['pop']) * 100, 2), axis=1)
dfx['pop_over75_ratio'] = dfx.apply(lambda row: round((row['pop_over75'] / row['pop']) * 100, 2), axis=1)
# dfx.info()
# dfx[['prefecture_jp','male_under15','male_adult','male_over65','male_over75']].head(3)
# dfx[['prefecture_jp','female_under15','female_adult','female_over65','female_over75']].head(3)
# dfx[['prefecture_jp','pop_under15','pop_adult','pop_over65','pop_over75']].head(3)
# dfx[['prefecture_jp','pop_male','pop_female','pop',]].head(3)
# dfx[['prefecture_jp','pop_under15_ratio','pop_adult_ratio','pop_over65_ratio','pop_over75_ratio']].head(3)
# dfx.isnull().sum()
# %%
### 0-4: Read a GeoJson file
url = r'https://money-or-ikigai.com/Menu/Python/Article/data/map/prefectures.json'
response = urllib.request.urlopen(url)
geo_data = response.read().decode('utf-8')
japan_prefectures = json.loads(geo_data)
# json_file = 'datasets/json/prefectures.json'
# japan_prefectures = json.load(open(json_file, 'r'))
# japan_prefectures
# %%
### 0-5: Load a prefecture id map dictionary from the geojson data
# Create an empty dictionary to store prefecture IDs
prefecture_id_map = {}
# Loop through the "features" list in the "japan_prefectures" dictionary
for feature in japan_prefectures['features']:
feature['id'] = feature['properties']['pref']
prefecture_id_map[feature['properties']['name']] = feature['id']
# prefecture_id_map
# %%
### 0-6: Load Japan geo data from a csv file
geo_csv = r'https://money-or-ikigai.com/Menu/Python/Article/data/map/japan_geo.csv'
# geo_csv = 'datasets/csv/japan_geo.csv'
geo_df = pd.read_csv(geo_csv)
# geo_df
# %%
### 0-7: Filter columns from the pandas dataframe.
geo_df = geo_df[['region_en','region_jp','prefecture_en','prefecture_jp']]
# geo_df
# %%
### 0-8: Concatenate the Japan census and geojason data horizontally based on the 'prefecture_jp' column
# Set the "prefecture_jp" column as the index for the "dfx" DataFrame
dfx_jp = dfx.set_index('prefecture_jp')
# Set the "prefecture_jp" column as the index for the "geo_df" DataFrame
geojp_df = geo_df.set_index('prefecture_jp')
# # Concatenate the "dfx" and "geo_df" DataFrames
# along the columns axis (axis=1) and store the result in "dfy"
dfy = pd.concat([dfx_jp, geojp_df], axis=1)
dfy.reset_index(inplace=True)
# dfy
# %%
### 0-9: Add a new column 'id' into the dataframe.
# Create a new column named "id" in the "dfy" DataFrame
# by applying a lambda function to the "prefecture_en" column.
# The lambda function maps each prefecture name in the "prefecture_en" column
# to its corresponding ID in the "prefecture_id_map" dictionary.
# The resulting IDs are assigned to the "id" column
dfy['id'] = dfy['prefecture_en'].apply(lambda x: prefecture_id_map[x])
# pd.options.display.max_rows = 999
raw_df = dfy.copy()
# raw_df.head(1)
# raw_df[['region_jp','region_en','prefecture_jp','prefecture_en','pop']].head(3)
# %%
### 1: Map population (2021)
# set a defulat template
pio.templates.default = 'plotly_dark'
### 1-1: population by prefecture
df = raw_df.copy()
fig = px.choropleth(
df,
locations='id',
geojson=japan_prefectures,
color='pop',
hover_name='prefecture_jp',
hover_data=['pop_male', 'pop_female'],
height=600,
labels=dict(
prefecture_jp='都道府県',
pop='人口',
pop_male='男性',
pop_female='女性',
),
title="px.choropleth(...): 都道府県別人口 (2021年度)",
)
fig.update_geos(fitbounds='locations', visible=False)
fig.show()
# %%
### 1-2: population ratio ages over 65 by prefecture
df = raw_df.copy()
fig = px.choropleth(
df,
locations='id',
geojson=japan_prefectures,
color='pop_over65_ratio',
hover_name='prefecture_jp',
hover_data=['pop_male', 'pop_female'],
height=600,
labels=dict(
pop_male='男性',
pop_female='女性',
prefecture_jp='都道府県',
pop_over65_ratio='高齢化率(%)',
),
title="px.choropleth(color='pop_over65_ratio'): 高齢化率(%) 65歳以上",
)
fig.update_geos(fitbounds='locations', visible=False)
fig.show()
# %%
### 1-3: population ratio ages over 75 by prefecture
df = raw_df.copy()
fig = px.choropleth(
df,
locations='id',
geojson=japan_prefectures,
color='pop_over75_ratio',
hover_name='prefecture_jp',
hover_data=['pop_male', 'pop_female'],
height=600,
labels=dict(
pop_male='男性',
pop_female='女性',
prefecture_jp='都道府県',
pop_over75_ratio='高齢化率(%)',
),
title="px.choropleth(color='pop_over75_ratio'): 高齢化率(%) 75歳以上",
)
fig.update_geos(fitbounds='locations', visible=False)
fig.show()
# %%
### 2: sunburst chart
### 2-1: population by region, prefecture
df = raw_df.copy()
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口"
)
fig.show()
# %%
### 2-2: population ages over 65
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over65',
hover_name='prefecture_jp',
color='pop_over65',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over65='高齢者',
pop_sum='総人口',
pop_over65_sum='高齢者',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over65'): 高齢者人口 (65歳以上)"
)
fig.show()
# %%
### 2-3: population ages over 75
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over75',
hover_name='prefecture_jp',
color='pop_over75',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over75='高齢者',
pop_sum='総人口',
pop_over75_sum='高齢者',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over75'): 高齢者人口 (75歳以上)"
)
fig.show()
# %%
### 2-4: population ratio ages over 65
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over65_ratio',
hover_name='prefecture_jp',
color='pop_over65_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over65_ratio='高齢化率',
pop_sum='総人口',
pop_over65_ratio_sum='高齢化率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over65_ratio'): 高齢化率 (65歳以上)"
)
fig.show()
# %%
### 2-5: population ratio ages over 75
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_over75_ratio',
hover_name='prefecture_jp',
color='pop_over75_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_over75_ratio='高齢化率',
pop_sum='総人口',
pop_over75_ratio_sum='高齢化率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_over75_ratio'): 高齢化率 (75歳以上)"
)
fig.show()
# %%
### 2-6: population ratio ages under 15
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_under15_ratio',
hover_name='prefecture_jp',
color='pop_under15_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_under15_ratio='少子化率',
pop_sum='総人口',
pop_under15_ratio_sum='少子化率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_under15_ratio'): 少子化率(15歳未満)"
)
fig.show()
# %%
### 2-7: population ratio adult (15~64)
fig = px.sunburst(df,
path=['region_jp','prefecture_jp'],
values='pop_adult_ratio',
hover_name='prefecture_jp',
color='pop_adult_ratio',
height=600,
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_adult_ratio='就業人口率',
pop_sum='総人口',
pop_adult_ratio_sum='就業人口率',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(values='pop_adult_ratio'): 就業人口率(15~64歳)"
)
fig.show()
# %%
### 3: pie chart
### 3-0: japan
df = raw_df.copy()
df['region'] = 'Japan'
# Group the "df" DataFrame by "region",
# summing the 'pop_under15', 'pop_adult', 'pop_over65' columns, and reset the index
grp_df = df.groupby('region')[['pop_under15', 'pop_adult', 'pop_over65']].sum().reset_index()
melted_df = pd.melt(grp_df,
id_vars=['region'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
# melted_df
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
height=600,
labels=dict(
category='分類',
value='人口'
),
title="px.pie(names='category', values='value'): 全国 (人口構成)"
)
fig.show()
# %%
### 3-0-1: add a holl and annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
category='分類',
value='人口'
),
title='px.pie(hole=0.4): 全国 (人口構成)'
)
fig.update_layout(
annotations=[dict(text='全国', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-0-2: add a pull
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
category='分類',
value='人口'
),
title='px.pie() + update_traces(pull=[0, 0, 0.2]): 全国 (人口構成)'
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='全国', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-0-3: sunburst()
df = raw_df.copy()
df['region'] = 'Japan'
# Group the "df" DataFrame by "region",
# summing the 'pop_under15', 'pop_adult', 'pop_over65', 'pop_over75' columns, and reset the index
grp_df = df.groupby('region')[['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75']].sum().reset_index()
melted_df = pd.melt(grp_df,
id_vars=['region'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
# melted_df
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
melted2_df['region'] = '全国'
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
# melted2_df
fig = px.sunburst(melted2_df,
path=['region', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['region', 'category', 'sub_category']): 全国 (人口構成)"
)
fig.show()
# %%
### 3-1: Tokyo
df = raw_df.copy()
df = df.query("prefecture_en == 'Tokyo'")
# df
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
# melted_df
### 3-1-1: add a holl + pull + annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.pie(names='category', values='value'): 東京都 (人口構成)"
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='東京都', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-1-2: sunburst()
df = raw_df.copy()
df = df.query("prefecture_en == 'Tokyo'")
# df
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted_df
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
melted2_df
fig = px.sunburst(melted2_df,
path=['prefecture_jp', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['prefecture_jp', 'category', 'sub_category']): 東京都 (人口構成)"
)
fig.show()
# %%
### 3-2: Akita
df = raw_df.copy()
df = df.query("prefecture_en == 'Akita'")
# df
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
### 3-2-1: add a holl + pull + annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.pie(names='category', values='value'): 秋田県 (人口構成)"
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='秋田県', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-2-2: sunburst()
df = raw_df.copy()
df = df.query("prefecture_en == 'Akita'")
# df
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted_df
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
melted2_df
fig = px.sunburst(melted2_df,
path=['prefecture_jp', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['prefecture_jp', 'category', 'sub_category']): 秋田県 (人口構成)"
)
fig.show()
# %%
### 3-3: okinawa
df = raw_df.copy()
df = df.query("prefecture_en == 'Okinawa'")
# df
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
### 3-3-1: add a hole + pull + annotations
fig = px.pie(melted_df,
names='category',
values='value',
color='category',
hole=0.4,
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.pie(names='category', values='value'): 沖縄県 (人口構成)"
)
fig.update_traces(
pull=[0, 0, 0.2]
)
fig.update_layout(
annotations=[dict(text='沖縄県', x=0.50, y=0.5, font_size=20, showarrow=False)]
)
fig.show()
# %%
### 3-3-2: sunburst()
df = raw_df.copy()
df = df.query("prefecture_en == 'Okinawa'")
df
melted_df = pd.melt(df,
id_vars=['prefecture_jp'],
value_vars=['pop_under15', 'pop_adult', 'pop_over65', 'pop_over75'],
var_name='category',
value_name='value')
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_under15','15歳未満'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_adult','15歳~64歳'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over65','65歳以上'))
melted_df['category'] = melted_df['category'].apply(lambda x: x.replace('pop_over75','75歳以上'))
melted_df
melted2_df = melted_df.copy()
melted2_df['sub_category'] = melted2_df['category']
category = melted2_df.columns.get_loc('category')
sub_category = melted2_df.columns.get_loc('sub_category')
melted2_df.iloc[0, sub_category] = None
melted2_df.iloc[1, sub_category] = None
melted2_df.iloc[2, sub_category] = '65歳~74歳'
melted2_df.iloc[3, category] = '65歳以上'
melted2_df
fig = px.sunburst(melted2_df,
path=['prefecture_jp', 'category', 'sub_category'],
values='value',
color='category',
height=600,
labels=dict(
labels='ラベル',
value='人口',
parent='65歳以上',
category='分類'
),
title="px.sunburst(path=['prefecture_jp', 'category', 'sub_category']): 沖縄県 (人口構成)"
)
fig.show()
# %%
### 4: bar chart
### 4-1: declining birth rate top 10 (under 15)
df = raw_df.copy()
df = df.nsmallest(10, 'pop_under15_ratio')
df.reset_index(inplace=True)
df['rank'] = df.index+1
df[['prefecture_jp','pop_under15_ratio','pop_under15','pop']]
fig = px.bar(df,
x='pop_under15_ratio', y='prefecture_jp',
color='prefecture_jp',
text='pop_under15_ratio',
orientation='h',
height=600,
labels=dict(
pop_under15_ratio='少子化率(15歳未満)',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_under15_ratio', y='prefecture_jp'): 少子化率(%) 上位10"
)
fig.show()
# %%
### 4-2: aging rate top 10 (over 65)
df = raw_df.copy()
df = df.nlargest(10, 'pop_over65_ratio')
df.reset_index(inplace=True)
df['rank'] = df.index+1
df[['prefecture_jp','pop_over65_ratio','pop_over65','pop']]
fig = px.bar(df,
x='pop_over65_ratio', y='prefecture_jp',
color='prefecture_jp',
text='pop_over65_ratio',
orientation='h',
height=600,
labels=dict(
pop_over65_ratio='高齢化率(65歳以上)',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_over65_ratio', y='prefecture_jp'): 高齢化率(%) 上位10"
)
fig.show()
# %%
### 4-3: aging rate top 10 (over 75)
df = raw_df.copy()
df = df.nlargest(10, 'pop_over75_ratio')
df.reset_index(inplace=True)
df['rank'] = df.index+1
df[['prefecture_jp','pop_over75_ratio','pop_over75','pop']]
fig = px.bar(df,
x='pop_over75_ratio', y='prefecture_jp',
color='prefecture_jp',
text='pop_over75_ratio',
orientation='h',
height=600,
labels=dict(
pop_over75_ratio='高齢化率(75歳以上)',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_over75_ratio', y='prefecture_jp'): 高齢化率(%) 上位10"
)
fig.show()
# %%