-
まずは、Pythonの開発環境を準備する
まずは、
「記事(Article137)」を参照して、
Pythonの開発環境を準備してください。
ここでは、Pythonのプロジェクトフォルダとして「Plotly」を使用しています。
図1は、Visual Studio Code(VS Code)の「Terminal」メニューから「New Terminal」を選択して、
「Terminal」ウィンドウを開いたときの画面です。
緑色の「(venv)」が表示されていれば、 Pythonの仮想環境が正常に作成されていることになります。
-
Visual Studio Codeを起動してプログラムファイルを作成する
Pythonの開発環境の準備が完了したら、 VS Codeを起動して新規のPythonファイル(*.py)を作成します。
ここで作成したPythonのファイルには「リスト9-1」のコードをコピペします。
図2は、VS Codeの画面です。
-
日本の人口データを分析(可視化)するためのデータを用意する
ここでは、総務省統計局のWebサイトからダウンロードした
人口データ(Excelファイル)を加工してPlotly Expressで分析するためのデータを用意します。
### 0: prepare population data
pd.options.display.max_rows = 6
csv_file = r'https://money-or-ikigai.com/Menu/Python/Article/data/map/japan_population_by_prefecture_year_gender(1920-2020).csv'
# csv_file = 'datasets/csv/japan_population_by_prefecture_year_gender(1920-2020).csv'
# Specify data types to optimize memory usage
dtypes = {
'prefecture_jp': 'category',
'year': 'int16',
'pop': 'int32',
'category': 'category',
'pop_female': 'int32',
'pop_male': 'int32'
}
# Read CSV file with optimized data types
df = pd.read_csv(csv_file, dtype=dtypes)
# df.info()
# df
# %%
# Melt data frame
melted_df = df.melt(id_vars=['prefecture_jp'], var_name='year', value_name='pop')
# Extract category and year from year column
melted_df[['category', 'year']] = melted_df['year'].str.split('_', expand=True)
melted_df['year'] = melted_df['year'].astype('int16')
melted_df['category'] = melted_df['category'].astype('category')
# melted_df.info()
# melted_df
# %%
# Pivot data frame
pivot_df = melted_df.pivot_table(values='pop',
index=['prefecture_jp', 'year'],
columns='category',
aggfunc=np.sum).reset_index()
# Rename columns
pivot_df.columns = ['prefecture_jp','year','pop_female','pop_male','pop']
# pivot_df.info()
# pivot_df
# %%
dfx = pivot_df.copy()
dfx['prev_pop'] = dfx.groupby(['prefecture_jp'])['pop'].shift(1)
dfx['pop_change_pct_5y'] = (dfx['pop'] - dfx['prev_pop']) / dfx['prev_pop'] * 100
dfx.drop('prev_pop', axis=1, inplace=True)
dfx['prev_pop'] = dfx.groupby(['prefecture_jp'])['pop_male'].shift(1)
dfx['pop_male_change_pct_5y'] = (dfx['pop_male'] - dfx['prev_pop']) / dfx['prev_pop'] * 100
dfx.drop('prev_pop', axis=1, inplace=True)
dfx['prev_pop'] = dfx.groupby(['prefecture_jp'])['pop_female'].shift(1)
dfx['pop_female_change_pct_5y'] = (dfx['pop_female'] - dfx['prev_pop']) / dfx['prev_pop'] * 100
dfx.drop('prev_pop', axis=1, inplace=True)
dfx.dropna(inplace=True)
# dfx.info()
# dfx.isnull().sum()
# %%
# Load Japan geography data from 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'
use_cols = ['prefecture_jp', 'prefecture_en', 'region_jp', 'region_en']
geo_df = pd.read_csv(geo_csv, usecols=use_cols)
# geo_df.info()
# geo_df
# %%
# Merge dataframes
dfy = pd.merge(dfx, geo_df, on='prefecture_jp')
raw_df = dfy.copy()
# raw_df.info()
# raw_df
図3-1では、総務省統計局のWebサイトからダウンロードしたExcelファイルをCSV形式で保存したCSVファイルを
PandasのDataFrameに取り込んでいます。
CSVファイルの列名(カラム名)は、Pythonで処理しやすいように「英語」に変換しています。
DataFrameは「prefecture_jp, pop_1920, male_1920, female_1920,...
pop_2020, male_2020, female_2020」の列から構成されています。
図3-2では、前出(図3-1)のDataFrameの内容を表示しています。
DataFrameには、「都道府県名、年度別人口、年度別男性人口、年度別女性人口」が格納されています。
なお、年度は1920年~2020年まで5年間隔になっています。
図3-3では、DataFrameの「melt()」メソッドで、
DataFrameを横形から縦形に変換しています。
DataFrameは「prefecture_jp, year, pop, category」の列から構成されています。
DataFrameには「都道府県名、年度、人口(総人口、男性、女性)、カテゴリー(pop, male, female)」が格納されています。
図3-4では、DataFrameの「povot_table()」メソッドでDataFrameを縦形から横形に変換しています。
DataFrameは「prefecture_jp, year, pop_female, pop_male, pop」の列から構成されています。
DataFrameには「都道府県名、年度、女性人口、男性人口、総人口」が格納されています。
図3-5では、年度別の人口増減率を計算して新規の列「pop_change_pct_5y, pop_male_change_pct_5y, pop_female_change_pct_5yr」に格納しています。
図3-6では、日本の地理データ(GeoJson)を読み込んで内容を表示しています。
このデータは、後述するステップで地方名(日本語、英語)、都道府県名(日本語、英語)をマージ(併合)するために使用します。
図3-7では、Pandasの「merge()」メソッドで2つのDataFrame(dfx, geodf)をマージ(併合)しています。
最後に、DataFrame(dfy)をDataFrame(raw_df)にコピーして保存しています。
最終版のDataFrame(raw_df)は、「region_jp, region_en, prefecutre_jp, prefecture_en, year, pop, pop_male, pop_female,...」
等の列から構成されています。
図3-8では最終版のDataFrame(raw_df)の内容を表示しています。
後述するステップでは、このDataFrame(raw_df)を使用して各種グラフを作成します。
-
Plotly ExpressのSunburst(サンバーストチャート)で人口データを可視化する
ここでは、Plotly Expressのサンバーストチャートで人口データを可視化します。
### 1: sunburst()
# set a defulat template
pio.templates.default = 'plotly_dark'
### 1-1: The population of each prefecture by region in 1945 (exclude okinawa)
df = raw_df.copy()
df = df.query("year == 1945 and prefecture_en != 'Okinawa'")
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']): 都道府県別人口 (1945年) "
)
fig.show()
# %%
### 1-2: sunburst() the population of each prefecture by region in 2020 (include okinawa)
df = raw_df.copy()
df = df.query("year == 2020")
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']): 都道府県別人口 (2020年) "
)
fig.show()
# %%
### 1-3: sunburst() comparing the populations of 1945 and 2020 (exclude okinawa)
df_1945 = raw_df.query("year == 1945 and prefecture_en != 'Okinawa'")
df_2020 = raw_df.query("year == 2020 and prefecture_en != 'Okinawa'")
fig_1945 = px.sunburst(df_1945,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (1945年) "
)
fig_2020 = px.sunburst(df_2020,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (2020年) "
)
fig = make_subplots(rows=1, cols=2,
specs=[[{'type': 'domain'}, {'type': 'domain'}]],
subplot_titles=['1945年の人口', '2020年の人口']
)
fig.add_trace(fig_1945.data[0], row=1, col=1)
fig.add_trace(fig_2020.data[0], row=1, col=2)
fig.update_layout(title='1945年と2020年の都道府県別人口')
fig.show()
図4-1では、地方、都道府県ごとの人口をサンバーストチャートで表示しています。
内側の円には「地方別の人口」、外側の円には「都道府県別の人口」がカラーマッピングされて表示されています。
「青色」から「黄色」になると人口が増加することを意味します。
内側の円から「地方名」をクリックすると、その地方の都道府県の人口が表示されます。
なお、ここでは1945年度の人口のチャートを表示しています。
図4-2では、前出(図4-1)のチャートから「関東地方」をクリックしています。
チャートには、関東地方の「都道府県」の人口がカラーマッピングされて表示されています。
「都道府県」にマウスをホバリングさせるとホバーテキストに「都道府県名、人口」等が表示されます。
ここでは「東京都」をホバリングさせています。
図4-3では、2020年度の人口をサンバーストチャートに表示させています。
図4-4では、1945年度と2020年度の人口をサンバーストチャートに表示して対比させています。
ここでは、1945年度と2020年度のサンバーストチャート(fig_1945, fig_202)を作成して
「make_subplots()」メソッドで追加したサブプロット(subplot)に「add_trace()」メソッドで追加しています。
「東京都」と「北海道」の人口に注目してください。
1945年度は「東京都、北海道」が「黄色」になっていますが、
2020年度は「東京都が黄色」、「北海道は紫色」になっています。
北海道の人口は「1945年は約3,518,000人」、「2020年は約5,224,000人」と増えているのですが、
他の都道府県と比べると増加率が低いことを意味します。
-
Plotly ExpressのTreemap(ツリーマップ)で人口データを可視化する
ここでは、Plotly Expressのツリーマップで人口データを可視化します。
### 2: treemap()
### 2-1: treemap() the population of each prefecture by region in 1945
df = raw_df.copy()
df = df.query("year == 1945 and prefecture_en != 'Okinawa'")
fig = px.treemap(df,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
height=600,
labels=dict(
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_jp='地方',
labels='都道府県',
parent='親'
),
title="px.treemap(path=['region_jp','prefecture_jp']): 都道府県別人口 (1945年)")
fig.show()
# %%
### 2-2: treemap() the population of each prefecture by region in 2020
df = raw_df.copy()
df = df.query("year == 2020")
fig = px.treemap(df,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
height=600,
labels=dict(
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_jp='地方',
labels='都道府県',
parent='親'
),
title="px.treemap(path=['region_jp','prefecture_jp']): 都道府県別人口 (2020年)")
fig.show()
# %%
### 2-3: treemap() comparing the populations of 1945 and 2020 (exclude okinawa)
df_1945 = raw_df.query("year == 1945 and prefecture_en != 'Okinawa'")
df_2020 = raw_df.query("year == 2020 and prefecture_en != 'Okinawa'")
fig_1945 = px.treemap(df_1945,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (1945年) "
)
fig_2020 = px.treemap(df_2020,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (2020年) "
)
fig = make_subplots(rows=1, cols=2,
specs=[[{'type': 'domain'}, {'type': 'domain'}]],
subplot_titles=['1945年の人口', '2020年の人口']
)
fig.add_trace(fig_1945.data[0], row=1, col=1)
fig.add_trace(fig_2020.data[0], row=1, col=2)
fig.update_layout(title='1945年と2020年の都道府県別人口')
fig.show()
図5-1では、1945年度の人口をツリーマップで表示しています。
ボックスが大きいほど人口が多いことを意味します。
さらに、ツリーマップには人口がカラーマッピングされて表示されています。
「青色」から「黄色」になると人口が増加することを意味します。
「地方名」のボックスをクリックすると、その地方の都道府県の人口が表示されます。
図5-2では、2020年度の人口をツリーマップで表示しています。
図5-3では、1945年度と2020年度の人口をツリーマップに表示して対比させています。
1945年度と2020年度のボックスの大きさを比較することで、
ざっくりした人口の増減が把握できます。
さらに、ボックスはカラーマッピングされているのでボックスの色を比較することで人口の増減を把握することもできます。
-
Plotly ExpressのBar(棒グラフ)で人口データを可視化する
ここでは、Plotly Expressの棒グラフで人口データを可視化します。
### 3: bar()
### 3-1: bar() population top 10
df = raw_df.copy()
# df = df.query("prefecture_en != 'Okinawa'")
df = df.sort_values(['prefecture_en','pop'], ascending=False)
df.drop_duplicates(subset=['prefecture_jp'], keep='first', inplace=True)
df.reset_index(drop=True, inplace=True)
# df.shape
# df
df = df.nlargest(10, 'pop')
# df.shape
df.reset_index(inplace=True)
df['rank'] = df.index+1
text = df.apply(lambda row: '{:,} ({})'.format(row['pop'], row['year']), axis=1)
fig = px.bar(df,
x='pop', y='prefecture_jp',
color='prefecture_jp',
text=text,
orientation='h',
height=600,
labels=dict(
text='人口',
pop='人口',
prefecture_jp='都道府県'
),
title="px.bar(x='pop', y='prefecture_jp'): 人口 上位10"
)
fig.show()
# %%
### 3-2: bar() population change rate 5-year percentage (%) top 10
df = raw_df.copy()
df = df.query("prefecture_en != 'Okinawa'")
df = df.sort_values(['prefecture_en','pop_change_pct_5y'], ascending=False)
df.drop_duplicates(subset=['prefecture_jp'], keep='first', inplace=True)
df.reset_index(drop=True, inplace=True)
# df.shape
# df
df = df.nlargest(10, 'pop_change_pct_5y')
# df.shape
df.reset_index(inplace=True)
df['rank'] = df.index+1
text = df.apply(lambda row: '{:.2f}% ({})'.format(row['pop_change_pct_5y'], row['year']), axis=1)
fig = px.bar(df,
x='pop_change_pct_5y', y='prefecture_jp',
color='prefecture_jp',
text=text,
orientation='h',
height=600,
labels=dict(
text='増減率',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_change_pct_5y', y='prefecture_jp'): 人口増減率 上位10"
)
fig.show()
# %%
### 3-3: bar() population change rate 5-year percentage (%) bottom 10
df = raw_df.copy()
df = df.query("prefecture_en != 'Okinawa'")
df = df.sort_values(['prefecture_en','pop_change_pct_5y'], ascending=True)
df.drop_duplicates(subset=['prefecture_jp'], keep='first', inplace=True)
df.reset_index(drop=True, inplace=True)
# df.shape
# df
df = df.nsmallest(10, 'pop_change_pct_5y')
df.reset_index(inplace=True)
df['rank'] = df.index+1
text = df.apply(lambda row: '{:.2f}% ({})'.format(row['pop_change_pct_5y'], row['year']), axis=1)
fig = px.bar(df,
x='pop_change_pct_5y', y='prefecture_jp',
color='prefecture_jp',
text=text,
orientation='h',
height=600,
labels=dict(
text='増減率',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_change_pct_5y', y='prefecture_jp'): 人口増減率 下位10"
)
fig.show()
# %%
### 3-4: bar() barmode='group'tokyo, osaka, aichi, fukuoka, hokkaido
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Osaka','Aichi','Fukuoka','Hokkaido']")
df = df.query("year == 1945 or year == 2020")
fig = px.bar(df,
x='year', y='pop',
color='prefecture_jp',
barmode='group', # relative(default), group, overlay
orientation='v',
text='prefecture_jp',
hover_data=['pop'],
height=600,
labels=dict(
pop='人口',
year='年度',
prefecture_jp='都道府県'
),
title="px.bar(x='year', y='pop'): 人口比較 1945 vs 2020 "
)
fig.show()
# %%
### 3-5: bar() barmode='group' tokyo, osaka, aichi, fukuoka, hokkaido
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Osaka','Aichi','Fukuoka','Hokkaido']")
df = df.query("year == 1945 or year == 2020")
fig = px.bar(df,
x='prefecture_jp', y='pop',
color='year',
barmode='group', # relative(default), group, overlay
orientation='v',
text='year',
hover_data=['pop'],
height=600,
labels=dict(
pop='人口',
year='年度',
prefecture_jp='都道府県'
),
title="px.bar(x='prefecture_jp', y='pop'): 人口比較 1945 vs 2020"
)
fig.show()
図6-1には、人口の上位10の都道府県を水平形の棒グラフに表示しています。
ここでは、年度別の人口を使用してランキングしています。
順位は、東京都、神奈川県、大阪府、愛知県、埼玉県,...の順になっています。
棒の内側には「人口と年度」が表示されています。
東京都の場合、2020年度がもっとも人口が多いということになります。
大阪府は2010年度がもっとも人口が多くなっています。
逆に言えば、2010年度よりも2020年度は人口が減っていることになります。
北海道は1995年度が人口がもっとも多く、兵庫県、静岡県は2005年度がもっとも人口が多くなっています。
図6-2では、人口の増加率の上位10の都道府県を水平形の棒グラフで表示しています。
ここでは、年度別の人口増減率を使用してランキングしています。
順位は、東京都、大阪府、神奈川県、福岡県、埼玉県,...の順になっています。
東京都は、1950年度が「79.96%」でもっとも人口が増えています。
これは、終戦後疎開先から東京に戻ってきたのが要因と思われます。
大阪府、神奈川県も同様と思われます。
図6-3では、人口増加率の下位10の都道府県を水平形の棒グラフに表示しています。
ここでは、年度別の人口増減率を使用してランキングしています。
棒グラフの内側には「増減率、年度」が表示されています。
東京都は1位で、「増減率が-52.57で年度が1945年」になっています。
これは戦時中に都民が疎開先に移動したのが要因と思われます。
大阪府と神奈川県も同様と思われます。
島根県、佐賀県などは過疎化が要因と思われます。
図6-4では、1945年度と2020年度の人口を比較しています。
ここでは、「北海道、大阪府、愛知県、東京都、福岡県」の人口を比較しています。
Plotly Expressの「bar()」メソッドには、
「x='year', y='pop', color='prefecture_jp'」を指定して
年度別にグラフを分離させています。
図6-5では、前出(図6-4)の棒グラフと同様1945年度と2020年度の人口を比較しています。
ここでは、
Plotly Expressの「bar()」メソッドに
「x='prefecture_jp', y='pop', color='year'」を指定して
都道府県別に棒グラフを分離させています。
引数「color」に年度「year」を指定しているので、
人口がカラーマッピングされて表示されます。
-
Plotly ExpressのLine(線グラフ)で人口データを可視化する
ここでは、Plotly Expressの線グラフで人口データを可視化します。
### 4: line()
### 4-1: line() top 5 (tokyo, kanagawa, osaka, aichi, saitama)
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Osaka','Aichi','Saitama']")
fig = px.line(df,
x='year', y='pop',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口推移 上位5"
)
fig.show()
# %%
### 4-2: line() tokyo, kanagawa, saitama, chiba, nagano
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Saitama','Chiba','Nagano']")
fig = px.line(df,
x='year', y='pop',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口推移 東京周辺"
)
fig.show()
# %%
### 4-3: line() tokyo, kanagawa, saitama, chiba, nagano
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Saitama','Chiba','Nagano']")
fig = px.line(df,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
pop_change_pct_5y='人口増減率'
),
title="px.line(x='year', y='pop_change_pct_5y'): 人口増減率 東京周辺"
)
fig.show()
# %%
### 4-4: line() top 5 (tokyo, osaka, kanagawa, fukuoka, saitama)
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Osaka','Kanagawa','Fukuoka','Saitama']")
fig = px.line(df,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口増減率 上位5"
)
fig.show()
# %%
### 4-5: line() tokyo update_traces(update_traces,line={'color':'red'})
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo']")
fig = px.line(df,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口増減率 東京 "
)
fig.update_traces(fill='tozeroy')
# fig.update_traces(
# fill='tozeroy',
# line={'color':'green'}
# )
# fig.update_traces(
# fill='tozeroy',
# line={'color':'red'}
# )
fig.show()
# %%
### 4-6: line() tokyo make_subplots, add_trace()
df = raw_df.query("prefecture_en == 'Tokyo'")
df_plus = df.copy()
df_minus = df.copy()
df_plus.loc[df_plus['pop_change_pct_5y'] < 0.0, 'pop_change_pct_5y'] = 0.0
df_minus.loc[df_minus['pop_change_pct_5y'] > 0.0, 'pop_change_pct_5y'] = 0.0
# df_plus['pop_change_pct_5y'] = df_plus['pop_change_pct_5y'].apply(lambda x: 0.0 if x < 0.0 else x)
# df_minus['pop_change_pct_5y'] = df_minus['pop_change_pct_5y'].apply(lambda x: 0.0 if x > 0.0 else x)
df_plus['prefecture_jp'] = '東京都(+)'
df_minus['prefecture_jp'] = '東京都(-)'
fig_plus = px.line(df_plus,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
)
)
fig_minus = px.line(df_minus,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
)
)
fig = make_subplots(rows=1, cols=1)
fig_plus.update_traces(
fill='tozeroy',
line={'color':'green'}
)
fig_minus.update_traces(
fill='tozeroy',
line={'color':'red'}
)
fig.add_trace(fig_plus.data[0], row=1, col=1)
fig.add_trace(fig_minus.data[0], row=1, col=1)
fig.update_layout(title="px.line(x='year', y='pop'): 人口増減率 東京")
fig.show()
図7-1では、人口の推移を線グラフで表示させています。
ここでは、人口の上位5位までの都道府県を表示しています。
1945年に人口が少なくなっているのは戦争が要因と思われます。
図7-2では、東京周辺の都道府県の人口を線グラフで表示させています。
1945年度に東京都が人口が減っていますがこれは戦時中に地方に疎開したのが要因と思われます。
図7-3では、東京周辺の都道府県の人口増減率を線グラフで表示させています。
1945年度に東京都、神奈川県の人口が激減していますが戦時中の疎開が要因と思われます。
1945年度に長野県、埼玉県の人口が増えているのは疎開先として他県から移動してきたのが要因と思われます。
図7-4では、人口増減率上位5位の都道府県の線グラフを表示させています。
1945年度は、埼玉県を除いて人口が激減しています。
図7-5では、東京都の人口増減率を線グラフで表示させています。
ここでは、figureクラスの「update_traces()」メソッドに
引数「fill='tozeroy'」を指定して面グラフのように塗りつぶしています。
図7-6では、東京都の人口増減率を線グラフで表示させています。
ここでは、プラスとマイナスの線グラフを作成して塗りつぶす色を分けています。
増減率がプラス(+)のときは「緑」、
増減率がマイナス(-)のときは「赤」で塗りつぶします。
-
Plotly ExpressのArea(面グラフ)で人口データを可視化する
ここでは、Plotly Expressの面グラフで人口データを可視化します。
### 5: area()
### 5-1: area() tokyo, kanagawa, saitama, chiba
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo', 'Kanagawa', 'Saitama', 'Chiba']")
fig = px.area(df,
x='year', y='pop',
color="prefecture_jp",
line_group='prefecture_jp',
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
),
title="px.area(x='year', y='pop'): 人口 東京周辺 "
)
fig.show()
# %%
### 5-2: area() tokyo
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo']")
fig = px.area(df,
x='year', y='pop_change_pct_5y',
color="prefecture_jp",
line_group='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.area(x='year', y='pop'): 人口増減率 東京 "
)
fig.show()
# %%
### 5-3: area() tokyo, kanagawa, saitama, chiba
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Saitama','Chiba']")
fig = px.area(df,
x='year', y='pop_change_pct_5y',
color="prefecture_jp",
line_group='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.area(x='year', y='pop'): 人口増減率"
)
fig.show()
図8-1では、東京都周辺の都道府県の人口を面グラフで表示させています。
図8-2では、東京都の人口増減率を面グラフで表示させています。
図8-3では、東京都周辺の都道府県の人口増減率を面グラフで表示させています。
-
全てのコードを掲載
ここでは、本記事で解説している全てのコードを掲載しています。
リスト9-1: Article153.py
# Article153 Population Analysis by Year and Gender (1920-2020) v20.py
# %%
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
from plotly.subplots import make_subplots
# %%
### 0: prepare population data
pd.options.display.max_rows = 6
csv_file = r'https://money-or-ikigai.com/Menu/Python/Article/data/map/japan_population_by_prefecture_year_gender(1920-2020).csv'
# csv_file = 'datasets/csv/japan_population_by_prefecture_year_gender(1920-2020).csv'
# Specify data types to optimize memory usage
dtypes = {
'prefecture_jp': 'category',
'year': 'int16',
'pop': 'int32',
'category': 'category',
'pop_female': 'int32',
'pop_male': 'int32'
}
# Read CSV file with optimized data types
df = pd.read_csv(csv_file, dtype=dtypes)
# df.info()
# df
# %%
# Melt data frame
melted_df = df.melt(id_vars=['prefecture_jp'], var_name='year', value_name='pop')
# Extract category and year from year column
melted_df[['category', 'year']] = melted_df['year'].str.split('_', expand=True)
melted_df['year'] = melted_df['year'].astype('int16')
melted_df['category'] = melted_df['category'].astype('category')
# melted_df.info()
# melted_df
# %%
# Pivot data frame
pivot_df = melted_df.pivot_table(values='pop',
index=['prefecture_jp', 'year'],
columns='category',
aggfunc=np.sum).reset_index()
# Rename columns
pivot_df.columns = ['prefecture_jp','year','pop_female','pop_male','pop']
# pivot_df.info()
# pivot_df
# %%
dfx = pivot_df.copy()
dfx['prev_pop'] = dfx.groupby(['prefecture_jp'])['pop'].shift(1)
dfx['pop_change_pct_5y'] = (dfx['pop'] - dfx['prev_pop']) / dfx['prev_pop'] * 100
dfx.drop('prev_pop', axis=1, inplace=True)
dfx['prev_pop'] = dfx.groupby(['prefecture_jp'])['pop_male'].shift(1)
dfx['pop_male_change_pct_5y'] = (dfx['pop_male'] - dfx['prev_pop']) / dfx['prev_pop'] * 100
dfx.drop('prev_pop', axis=1, inplace=True)
dfx['prev_pop'] = dfx.groupby(['prefecture_jp'])['pop_female'].shift(1)
dfx['pop_female_change_pct_5y'] = (dfx['pop_female'] - dfx['prev_pop']) / dfx['prev_pop'] * 100
dfx.drop('prev_pop', axis=1, inplace=True)
dfx.dropna(inplace=True)
# dfx.info()
# dfx.isnull().sum()
# %%
# Load Japan geography data from 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'
use_cols = ['prefecture_jp', 'prefecture_en', 'region_jp', 'region_en']
geo_df = pd.read_csv(geo_csv, usecols=use_cols)
# geo_df.info()
# geo_df
# %%
# Merge dataframes
dfy = pd.merge(dfx, geo_df, on='prefecture_jp')
raw_df = dfy.copy()
# raw_df.info()
# raw_df
# %%
### 1: sunburst()
# set a defulat template
pio.templates.default = 'plotly_dark'
### 1-1: The population of each prefecture by region in 1945 (exclude okinawa)
df = raw_df.copy()
df = df.query("year == 1945 and prefecture_en != 'Okinawa'")
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']): 都道府県別人口 (1945年) "
)
fig.show()
# %%
### 1-2: sunburst() the population of each prefecture by region in 2020 (include okinawa)
df = raw_df.copy()
df = df.query("year == 2020")
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']): 都道府県別人口 (2020年) "
)
fig.show()
# %%
### 1-3: sunburst() comparing the populations of 1945 and 2020 (exclude okinawa)
df_1945 = raw_df.query("year == 1945 and prefecture_en != 'Okinawa'")
df_2020 = raw_df.query("year == 2020 and prefecture_en != 'Okinawa'")
fig_1945 = px.sunburst(df_1945,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (1945年) "
)
fig_2020 = px.sunburst(df_2020,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (2020年) "
)
fig = make_subplots(rows=1, cols=2,
specs=[[{'type': 'domain'}, {'type': 'domain'}]],
subplot_titles=['1945年の人口', '2020年の人口']
)
fig.add_trace(fig_1945.data[0], row=1, col=1)
fig.add_trace(fig_2020.data[0], row=1, col=2)
fig.update_layout(title='1945年と2020年の都道府県別人口')
fig.show()
# %%
### 2: treemap()
### 2-1: treemap() the population of each prefecture by region in 1945
df = raw_df.copy()
df = df.query("year == 1945 and prefecture_en != 'Okinawa'")
fig = px.treemap(df,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
height=600,
labels=dict(
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_jp='地方',
labels='都道府県',
parent='親'
),
title="px.treemap(path=['region_jp','prefecture_jp']): 都道府県別人口 (1945年)")
fig.show()
# %%
### 2-2: treemap() the population of each prefecture by region in 2020
df = raw_df.copy()
df = df.query("year == 2020")
fig = px.treemap(df,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
height=600,
labels=dict(
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_jp='地方',
labels='都道府県',
parent='親'
),
title="px.treemap(path=['region_jp','prefecture_jp']): 都道府県別人口 (2020年)")
fig.show()
# %%
### 2-3: treemap() comparing the populations of 1945 and 2020 (exclude okinawa)
df_1945 = raw_df.query("year == 1945 and prefecture_en != 'Okinawa'")
df_2020 = raw_df.query("year == 2020 and prefecture_en != 'Okinawa'")
fig_1945 = px.treemap(df_1945,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (1945年) "
)
fig_2020 = px.treemap(df_2020,
path=['region_jp','prefecture_jp'],
values='pop',
hover_name='prefecture_jp',
color='pop',
labels=dict(
labels='都道府県',
parent='地方',
pop='人口',
pop_sum='総人口',
prefecture_jp='都道府県',
region_en='地域'
),
title="px.sunburst(path=['region_jp','prefecture_jp']): 都道府県別人口 (2020年) "
)
fig = make_subplots(rows=1, cols=2,
specs=[[{'type': 'domain'}, {'type': 'domain'}]],
subplot_titles=['1945年の人口', '2020年の人口']
)
fig.add_trace(fig_1945.data[0], row=1, col=1)
fig.add_trace(fig_2020.data[0], row=1, col=2)
fig.update_layout(title='1945年と2020年の都道府県別人口')
fig.show()
# %%
### 3: bar()
### 3-1: bar() population top 10
df = raw_df.copy()
# df = df.query("prefecture_en != 'Okinawa'")
df = df.sort_values(['prefecture_en','pop'], ascending=False)
df.drop_duplicates(subset=['prefecture_jp'], keep='first', inplace=True)
df.reset_index(drop=True, inplace=True)
# df.shape
# df
df = df.nlargest(10, 'pop')
# df.shape
df.reset_index(inplace=True)
df['rank'] = df.index+1
text = df.apply(lambda row: '{:,} ({})'.format(row['pop'], row['year']), axis=1)
fig = px.bar(df,
x='pop', y='prefecture_jp',
color='prefecture_jp',
text=text,
orientation='h',
height=600,
labels=dict(
text='人口',
pop='人口',
prefecture_jp='都道府県'
),
title="px.bar(x='pop', y='prefecture_jp'): 人口 上位10"
)
fig.show()
# %%
### 3-2: bar() population change rate 5-year percentage (%) top 10
df = raw_df.copy()
df = df.query("prefecture_en != 'Okinawa'")
df = df.sort_values(['prefecture_en','pop_change_pct_5y'], ascending=False)
df.drop_duplicates(subset=['prefecture_jp'], keep='first', inplace=True)
df.reset_index(drop=True, inplace=True)
# df.shape
# df
df = df.nlargest(10, 'pop_change_pct_5y')
# df.shape
df.reset_index(inplace=True)
df['rank'] = df.index+1
text = df.apply(lambda row: '{:.2f}% ({})'.format(row['pop_change_pct_5y'], row['year']), axis=1)
fig = px.bar(df,
x='pop_change_pct_5y', y='prefecture_jp',
color='prefecture_jp',
text=text,
orientation='h',
height=600,
labels=dict(
text='増減率',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_change_pct_5y', y='prefecture_jp'): 人口増減率 上位10"
)
fig.show()
# %%
### 3-3: bar() population change rate 5-year percentage (%) bottom 10
df = raw_df.copy()
df = df.query("prefecture_en != 'Okinawa'")
df = df.sort_values(['prefecture_en','pop_change_pct_5y'], ascending=True)
df.drop_duplicates(subset=['prefecture_jp'], keep='first', inplace=True)
df.reset_index(drop=True, inplace=True)
# df.shape
# df
df = df.nsmallest(10, 'pop_change_pct_5y')
df.reset_index(inplace=True)
df['rank'] = df.index+1
text = df.apply(lambda row: '{:.2f}% ({})'.format(row['pop_change_pct_5y'], row['year']), axis=1)
fig = px.bar(df,
x='pop_change_pct_5y', y='prefecture_jp',
color='prefecture_jp',
text=text,
orientation='h',
height=600,
labels=dict(
text='増減率',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県'
),
title="px.bar(x='pop_change_pct_5y', y='prefecture_jp'): 人口増減率 下位10"
)
fig.show()
# %%
### 3-4: bar() barmode='group'tokyo, osaka, aichi, fukuoka, hokkaido
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Osaka','Aichi','Fukuoka','Hokkaido']")
df = df.query("year == 1945 or year == 2020")
fig = px.bar(df,
x='year', y='pop',
color='prefecture_jp',
barmode='group', # relative(default), group, overlay
orientation='v',
text='prefecture_jp',
hover_data=['pop'],
height=600,
labels=dict(
pop='人口',
year='年度',
prefecture_jp='都道府県'
),
title="px.bar(x='year', y='pop'): 人口比較 1945 vs 2020 "
)
fig.show()
# %%
### 3-5: bar() barmode='group' tokyo, osaka, aichi, fukuoka, hokkaido
df = raw_df.copy()
# df = df.query("prefecture_en in ['Tokyo']")
df = df.query("prefecture_en in ['Tokyo','Osaka','Aichi','Fukuoka','Hokkaido']")
df = df.query("year == 1945 or year == 2020")
fig = px.bar(df,
x='prefecture_jp', y='pop',
color='year',
barmode='group', # relative(default), group, overlay
orientation='v',
text='year',
hover_data=['pop'],
height=600,
labels=dict(
pop='人口',
year='年度',
prefecture_jp='都道府県'
),
title="px.bar(x='prefecture_jp', y='pop'): 人口比較 1945 vs 2020"
)
fig.show()
# %%
### 4: line()
### 4-1: line() top 5 (tokyo, kanagawa, osaka, aichi, saitama)
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Osaka','Aichi','Saitama']")
fig = px.line(df,
x='year', y='pop',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口推移 上位5"
)
fig.show()
# %%
### 4-2: line() tokyo, kanagawa, saitama, chiba, nagano
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Saitama','Chiba','Nagano']")
fig = px.line(df,
x='year', y='pop',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口推移 東京周辺"
)
fig.show()
# %%
### 4-3: line() tokyo, kanagawa, saitama, chiba, nagano
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Saitama','Chiba','Nagano']")
fig = px.line(df,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
pop_change_pct_5y='人口増減率'
),
title="px.line(x='year', y='pop_change_pct_5y'): 人口増減率 東京周辺"
)
fig.show()
# %%
### 4-4: line() top 5 (tokyo, osaka, kanagawa, fukuoka, saitama)
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Osaka','Kanagawa','Fukuoka','Saitama']")
fig = px.line(df,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
markers=True,
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口増減率 上位5"
)
fig.show()
# %%
### 4-5: line() tokyo update_traces(update_traces,line={'color':'red'})
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo']")
fig = px.line(df,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.line(x='year', y='pop'): 人口増減率 東京 "
)
fig.update_traces(fill='tozeroy')
# fig.update_traces(
# fill='tozeroy',
# line={'color':'green'}
# )
# fig.update_traces(
# fill='tozeroy',
# line={'color':'red'}
# )
fig.show()
# %%
### 4-6: line() tokyo make_subplots, add_trace()
df = raw_df.query("prefecture_en == 'Tokyo'")
df_plus = df.copy()
df_minus = df.copy()
df_plus.loc[df_plus['pop_change_pct_5y'] < 0.0, 'pop_change_pct_5y'] = 0.0
df_minus.loc[df_minus['pop_change_pct_5y'] > 0.0, 'pop_change_pct_5y'] = 0.0
# df_plus['pop_change_pct_5y'] = df_plus['pop_change_pct_5y'].apply(lambda x: 0.0 if x < 0.0 else x)
# df_minus['pop_change_pct_5y'] = df_minus['pop_change_pct_5y'].apply(lambda x: 0.0 if x > 0.0 else x)
df_plus['prefecture_jp'] = '東京都(+)'
df_minus['prefecture_jp'] = '東京都(-)'
fig_plus = px.line(df_plus,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
)
)
fig_minus = px.line(df_minus,
x='year', y='pop_change_pct_5y',
color='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
)
)
fig = make_subplots(rows=1, cols=1)
fig_plus.update_traces(
fill='tozeroy',
line={'color':'green'}
)
fig_minus.update_traces(
fill='tozeroy',
line={'color':'red'}
)
fig.add_trace(fig_plus.data[0], row=1, col=1)
fig.add_trace(fig_minus.data[0], row=1, col=1)
fig.update_layout(title="px.line(x='year', y='pop'): 人口増減率 東京")
fig.show()
# %%
### 5: area()
### 5-1: area() tokyo, kanagawa, saitama, chiba
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo', 'Kanagawa', 'Saitama', 'Chiba']")
fig = px.area(df,
x='year', y='pop',
color="prefecture_jp",
line_group='prefecture_jp',
labels=dict(
year='年度',
pop='人口',
prefecture_jp='都道府県',
),
title="px.area(x='year', y='pop'): 人口 東京周辺 "
)
fig.show()
# %%
### 5-2: area() tokyo
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo']")
fig = px.area(df,
x='year', y='pop_change_pct_5y',
color="prefecture_jp",
line_group='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.area(x='year', y='pop'): 人口増減率 東京 "
)
fig.show()
# %%
### 5-3: area() tokyo, kanagawa, saitama, chiba
df = raw_df.copy()
df = df.query("prefecture_en in ['Tokyo','Kanagawa','Saitama','Chiba']")
fig = px.area(df,
x='year', y='pop_change_pct_5y',
color="prefecture_jp",
line_group='prefecture_jp',
labels=dict(
year='年度',
pop_change_pct_5y='人口増減率',
prefecture_jp='都道府県',
),
title="px.area(x='year', y='pop'): 人口増減率"
)
fig.show()