Python {Article153}

ようこそ「Python」へ...

Plotlyでデータサイエンティストのように日本の人口データから年度別の人口増減率を分析して見る【Pythonデータ分析】

ここでは、Plotlyを使用してデータサイエンティストのように日本の人口データから年度別の人口増減率を可視化して分析する方法を解説します。 本記事では、総務省統計局が公開している「年度別・性別人口データ(2020年度)」を使用しています。 このファイル(Excel)には、 大正9年(1920年)から令和2年(2020年)までの都道府県の人口データが5年間隔で男女別に格納されています。 ここでは、これらの人口データを利用して都道府県別の人口と増減率を可視化して分析します。

Pythonには、Matplotlib, Seaborn, Plotly Express, Plotly Graph Objectsなどのグラフを作成するライブラリがあります。

MatplotlibとSeabornは、 静的なグラフを作成するために設計されたPythonライブラリであるのに対して、 Plotlyはインタラクティブなグラフを作成するために設計されています。 したがって、Plotlyは、グラフを拡大・縮小したり、 マウスホーバーでデータ値を表示するなどのインタラクティブな操作が可能で、 より直感的なデータの解析ができるようになっています。 なので、ここではPlotlyのインタラクティブな機能を利用してデータを解析します。

なお、Plotlyは Dashを使用することによりWebブラウザ上で対話的なデータ可視化も可能になります。 Plotlyは、以下のようなさまざまなグラフを作成してデータを可視化することができます。
  • Scatter Plot(散布図):
    用途:2つの量的変数間の関係を可視化するために使用されます。
    特徴:点がプロットされ、X軸とY軸に数値が表示されます。 複数のグループを区別する場合、色や形状で表現できます。

  • Line Plot(折れ線グラフ):
    用途:量的変数の時間的変化を可視化するために使用されます。
    特徴:点を線で接続し、時間や数値の連続した変化を表現します。

  • Bar Chart(棒グラフ):
    用途:カテゴリ別の数量や割合の比較を可視化するために使用されます。
    特徴:カテゴリ(X軸)と数値(Y軸)が表示され、複数のグループを区別する場合、色やパターンで表現できます。

  • Pie Chart(円グラフ):
    用途:カテゴリ内の数量の比率を可視化するために使用されます。
    特徴:円形で表現され、各カテゴリの部分が円周上に表示されます。 一般的には、4つ以上のカテゴリに使用すると読みやすくなります。

  • Histogram(ヒストグラム):
    用途:数量データの分布を可視化するために使用されます。
    特徴:数値の範囲がビンに分割され、ビンごとにデータが表示されます。 ビンの幅は、分布の特性に応じて調整できます。

  • Sunburst(サンバーストチャート):
    用途:階層的なカテゴリ構造を可視化するために使用されます。
    特徴:中心から外側に向かってカテゴリが分割され、各セグメントの大きさは割合で表示されます。

  • Treemap(ツリーマップ):
    用途:階層的なカテゴリ構造を可視化するために使用されます。サンバーストチャートと同じく、会社の部門、チーム、プロジェクトなどの関係性を示すことができます。
    特徴:四角形の領域がカテゴリを表し、領域の大きさはカテゴリの値に比例します。 それぞれの四角形は、色やラベルなどの要素を持つことができます。ツリーマップは、視覚的に洞察力を得るために、大量のデータを表示するのに適しています。

  • Choropleth(コロプレス図):
    用途:地理的なデータを可視化するために使用されます。地域ごとの数量や比率を示すことができます。たとえば、国別の人口、都市別の収入などを表示できます。
    特徴:地図上の地域ごとに色を割り当てて表示します。 色は、数量や比率の大小に応じて異なり、カラーマップを選択することができます。 コロプレス図は、地域ごとのパターンを見つけるのに役立ちます。また、マウスオーバー時に詳細な情報を表示することもできます。

これらのグラフはすべて、Plotly Expressで簡単に作成することができます。 また、Plotly Expressは、多数のオプションやカスタマイズ機能を提供しているため、 データの視覚化において幅広い用途に利用できます。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。
click image to zoom!
図A
click image to zoom!
図B
click image to zoom!
図C
click image to zoom!
図D
click image to zoom!
図E
click image to zoom!
図F
click image to zoom!
図G
click image to zoom!
図H
click image to zoom!
図I
click image to zoom!
図J
click image to zoom!
図K
click image to zoom!
図L
click image to zoom!
図M

Plotly Expressでデータサイエンティストのように日本の人口データから人口増減率を分析して見る【Pythonデータ分析】

  1. まずは、Pythonの開発環境を準備する

    まずは、 「記事(Article137)」を参照して、 Pythonの開発環境を準備してください。 ここでは、Pythonのプロジェクトフォルダとして「Plotly」を使用しています。

    click image to zoom!
    図1
    図1は、Visual Studio Code(VS Code)の「Terminal」メニューから「New Terminal」を選択して、 「Terminal」ウィンドウを開いたときの画面です。 緑色の「(venv)」が表示されていれば、 Pythonの仮想環境が正常に作成されていることになります。
  2. Visual Studio Codeを起動してプログラムファイルを作成する

    Pythonの開発環境の準備が完了したら、 VS Codeを起動して新規のPythonファイル(*.py)を作成します。 ここで作成したPythonのファイルには「リスト9-1」のコードをコピペします。

    click image to zoom!
    図2
    図2は、VS Codeの画面です。
  3. 日本の人口データを分析(可視化)するためのデータを用意する

    ここでは、総務省統計局の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    
    click image to zoom!
    図3-1
    図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」の列から構成されています。

    click image to zoom!
    図3-2
    図3-2では、前出(図3-1)のDataFrameの内容を表示しています。 DataFrameには、「都道府県名、年度別人口、年度別男性人口、年度別女性人口」が格納されています。 なお、年度は1920年~2020年まで5年間隔になっています。

    click image to zoom!
    図3-3
    図3-3では、DataFrameの「melt()」メソッドで、 DataFrameを横形から縦形に変換しています。 DataFrameは「prefecture_jp, year, pop, category」の列から構成されています。 DataFrameには「都道府県名、年度、人口(総人口、男性、女性)、カテゴリー(pop, male, female)」が格納されています。

    click image to zoom!
    図3-4
    図3-4では、DataFrameの「povot_table()」メソッドでDataFrameを縦形から横形に変換しています。 DataFrameは「prefecture_jp, year, pop_female, pop_male, pop」の列から構成されています。 DataFrameには「都道府県名、年度、女性人口、男性人口、総人口」が格納されています。

    click image to zoom!
    図3-5
    図3-5では、年度別の人口増減率を計算して新規の列「pop_change_pct_5y, pop_male_change_pct_5y, pop_female_change_pct_5yr」に格納しています。

    click image to zoom!
    図3-6
    図3-6では、日本の地理データ(GeoJson)を読み込んで内容を表示しています。 このデータは、後述するステップで地方名(日本語、英語)、都道府県名(日本語、英語)をマージ(併合)するために使用します。

    click image to zoom!
    図3-7
    図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,...」 等の列から構成されています。

    click image to zoom!
    図3-8
    図3-8では最終版のDataFrame(raw_df)の内容を表示しています。 後述するステップでは、このDataFrame(raw_df)を使用して各種グラフを作成します。
  4. 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()  
    click image to zoom!
    図4-1
    図4-1では、地方、都道府県ごとの人口をサンバーストチャートで表示しています。 内側の円には「地方別の人口」、外側の円には「都道府県別の人口」がカラーマッピングされて表示されています。 「青色」から「黄色」になると人口が増加することを意味します。 内側の円から「地方名」をクリックすると、その地方の都道府県の人口が表示されます。 なお、ここでは1945年度の人口のチャートを表示しています。

    click image to zoom!
    図4-2
    図4-2では、前出(図4-1)のチャートから「関東地方」をクリックしています。 チャートには、関東地方の「都道府県」の人口がカラーマッピングされて表示されています。 「都道府県」にマウスをホバリングさせるとホバーテキストに「都道府県名、人口」等が表示されます。 ここでは「東京都」をホバリングさせています。

    click image to zoom!
    図4-3
    図4-3では、2020年度の人口をサンバーストチャートに表示させています。

    click image to zoom!
    図4-4
    図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人」と増えているのですが、 他の都道府県と比べると増加率が低いことを意味します。
  5. 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()  
    click image to zoom!
    図5-1
    図5-1では、1945年度の人口をツリーマップで表示しています。 ボックスが大きいほど人口が多いことを意味します。 さらに、ツリーマップには人口がカラーマッピングされて表示されています。 「青色」から「黄色」になると人口が増加することを意味します。 「地方名」のボックスをクリックすると、その地方の都道府県の人口が表示されます。

    click image to zoom!
    図5-2
    図5-2では、2020年度の人口をツリーマップで表示しています。

    click image to zoom!
    図5-3
    図5-3では、1945年度と2020年度の人口をツリーマップに表示して対比させています。 1945年度と2020年度のボックスの大きさを比較することで、 ざっくりした人口の増減が把握できます。 さらに、ボックスはカラーマッピングされているのでボックスの色を比較することで人口の増減を把握することもできます。
  6. 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()  
    click image to zoom!
    図6-1
    図6-1には、人口の上位10の都道府県を水平形の棒グラフに表示しています。 ここでは、年度別の人口を使用してランキングしています。 順位は、東京都、神奈川県、大阪府、愛知県、埼玉県,...の順になっています。 棒の内側には「人口と年度」が表示されています。 東京都の場合、2020年度がもっとも人口が多いということになります。 大阪府は2010年度がもっとも人口が多くなっています。 逆に言えば、2010年度よりも2020年度は人口が減っていることになります。 北海道は1995年度が人口がもっとも多く、兵庫県、静岡県は2005年度がもっとも人口が多くなっています。

    click image to zoom!
    図6-2
    図6-2では、人口の増加率の上位10の都道府県を水平形の棒グラフで表示しています。 ここでは、年度別の人口増減率を使用してランキングしています。 順位は、東京都、大阪府、神奈川県、福岡県、埼玉県,...の順になっています。 東京都は、1950年度が「79.96%」でもっとも人口が増えています。 これは、終戦後疎開先から東京に戻ってきたのが要因と思われます。 大阪府、神奈川県も同様と思われます。

    click image to zoom!
    図6-3
    図6-3では、人口増加率の下位10の都道府県を水平形の棒グラフに表示しています。 ここでは、年度別の人口増減率を使用してランキングしています。 棒グラフの内側には「増減率、年度」が表示されています。 東京都は1位で、「増減率が-52.57で年度が1945年」になっています。 これは戦時中に都民が疎開先に移動したのが要因と思われます。 大阪府と神奈川県も同様と思われます。 島根県、佐賀県などは過疎化が要因と思われます。

    click image to zoom!
    図6-4
    図6-4では、1945年度と2020年度の人口を比較しています。 ここでは、「北海道、大阪府、愛知県、東京都、福岡県」の人口を比較しています。 Plotly Expressの「bar()」メソッドには、 「x='year', y='pop', color='prefecture_jp'」を指定して 年度別にグラフを分離させています。

    click image to zoom!
    図6-5
    図6-5では、前出(図6-4)の棒グラフと同様1945年度と2020年度の人口を比較しています。 ここでは、 Plotly Expressの「bar()」メソッドに 「x='prefecture_jp', y='pop', color='year'」を指定して 都道府県別に棒グラフを分離させています。 引数「color」に年度「year」を指定しているので、 人口がカラーマッピングされて表示されます。
  7. 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()  
    click image to zoom!
    図7-1
    図7-1では、人口の推移を線グラフで表示させています。 ここでは、人口の上位5位までの都道府県を表示しています。 1945年に人口が少なくなっているのは戦争が要因と思われます。

    click image to zoom!
    図7-2
    図7-2では、東京周辺の都道府県の人口を線グラフで表示させています。 1945年度に東京都が人口が減っていますがこれは戦時中に地方に疎開したのが要因と思われます。

    click image to zoom!
    図7-3
    図7-3では、東京周辺の都道府県の人口増減率を線グラフで表示させています。 1945年度に東京都、神奈川県の人口が激減していますが戦時中の疎開が要因と思われます。 1945年度に長野県、埼玉県の人口が増えているのは疎開先として他県から移動してきたのが要因と思われます。

    click image to zoom!
    図7-4
    図7-4では、人口増減率上位5位の都道府県の線グラフを表示させています。 1945年度は、埼玉県を除いて人口が激減しています。

    click image to zoom!
    図7-5
    図7-5では、東京都の人口増減率を線グラフで表示させています。 ここでは、figureクラスの「update_traces()」メソッドに 引数「fill='tozeroy'」を指定して面グラフのように塗りつぶしています。

    click image to zoom!
    図7-6
    図7-6では、東京都の人口増減率を線グラフで表示させています。 ここでは、プラスとマイナスの線グラフを作成して塗りつぶす色を分けています。 増減率がプラス(+)のときは「緑」、 増減率がマイナス(-)のときは「赤」で塗りつぶします。
  8. 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()  
    click image to zoom!
    図8-1
    図8-1では、東京都周辺の都道府県の人口を面グラフで表示させています。

    click image to zoom!
    図8-2
    図8-2では、東京都の人口増減率を面グラフで表示させています。

    click image to zoom!
    図8-3
    図8-3では、東京都周辺の都道府県の人口増減率を面グラフで表示させています。
  9. 全てのコードを掲載

    ここでは、本記事で解説している全てのコードを掲載しています。

    リスト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()