Python {Article146}

ようこそ「Python」へ...

Python: Plotlyで棒グラフ(Bar Charts)を作成する (Plotly Express, Plotly Graph Objects【Plotly超入門】

ここでは、Plotlyを使用して棒グラフ(Bar Charts)を作成する方法を解説します。 Pythonでグラフを作成するためのライブラリとして、 Matplotlib、Seaborn、Plotly Express、Plotly Graph Objectsなどがあります。

MatplotlibはPythonで最も広く使われているグラフ描画ライブラリの1つで、 様々なグラフを作成することができます。線グラフ、ヒストグラム、散布図、バブルチャート、等々の作成ができます。 また、多数のカスタマイズオプションがあります。

Seabornは、統計データを視覚化するために設計されたPythonのデータ可視化ライブラリです。 Seabornを使用すると、Matplotlibよりも簡単に美しく見栄えのするグラフを作成することができます。 特に、箱ひげ図やヒートマップなど、統計分析でよく用いられるグラフの描画に優れています。

Plotlyは、インタラクティブなグラフを作成するために設計されたPythonライブラリです。 Plotlyを使用すると、HTMLでエクスポートできるブラウザで表示されるグラフを作成することができます。 また、Plotlyには、グラフの拡大・縮小や標準偏差などを示す誤差バーなどのインタラクティブな機能が多数あります。

MatplotlibとSeabornは、 静的なグラフを作成するために設計されたPythonライブラリであるのに対して、 Plotlyはインタラクティブなグラフを作成するために設計されています。 したがって、Plotlyは、グラフを拡大・縮小したり、マウスオーバーでデータ値を表示するなどのインタラクティブな操作が可能で、 より直感的なデータの解析ができるようになっています。 これは、MatplotlibやSeabornでは実現できない機能です。 それぞれのライブラリの用途と特徴をまとめると以下にようになります。
  • Matplotlib:
    • 2Dグラフ描画のためのデファクトスタンダード的なライブラリ
    • 線グラフ、散布図、ヒストグラム、棒グラフなど多数のグラフタイプに対応
    • グラフを細かくカスタマイズすることができ、高度なカスタマイズも可能
    • 豊富なドキュメントやチュートリアルがあり、比較的習得しやすい
  • Seaborn:
    • Matplotlibのラッパーライブラリの一つで、Matplotlibの機能を拡張したライブラリ
    • Matplotlibに比べて、より美しく見やすいグラフを作成できる
    • ヒストグラム、カーネル密度推定、箱ひげ図、散布図行列などの高度なグラフに対応
    • データの分布を可視化するための専用の機能を提供
    • ドキュメントが充実しており、初心者でも扱いやすい
  • Plotly Express:
    • Plotlyの高水準APIの一つで、より簡単にグラフを作成できる
    • MatplotlibやSeabornよりもインタラクティブなグラフを作成できる
    • 線グラフ、散布図、バブルチャート、棒グラフ、箱ひげ図、ヒートマップなど多数のグラフタイプに対応
    • グラフの色、軸の範囲、ラベルなどを簡単にカスタマイズできる
    • 簡単にアニメーション化することができる
  • Plotly Graph Objects:
    • Plotlyの低水準APIの一つで、より細かいカスタマイズが可能
    • グラフの全ての要素をコントロールすることができ、より高度なグラフを作成できる
    • グラフの軸、レイアウト、トレースなどの設定が可能
    • インタラクティブなグラフを簡単に作成することができる
    • ドキュメントが充実しており、高度なグラフを作成するための情報が豊富に提供されている
ここでは、Plotly Expressを中心に棒グラフを作成する方法を解説します。 Plotly Expressで棒グラフを作成するには、以下の手順で行うことをおすすめします。
  • Step1:
    Plotlyで各種グラフを作成するには、 「Plotly Graphing Library」のサイトから、 グラフの種類を選択します。 Plotlyのグラフは「Fundamentals」「Basic Charts」「Statistical Charts」「Scientific Charts」 「Financial Charts」「Maps」「Artificial Intelligence and Machine Learning」 「Bioinformatics」「3D Charts」「Subplots」などに分類されています。 たとえば、今回のように棒グラフを作成したいときは、 「Bar Charts」を選択します。

  • Step2:
    Bar Charts」のサイトには、 棒グラフを作成するためのサンプルコードと棒グラフが掲載されています。 これらの中から自分が作成したいものに近い棒グラフのサンプルを参考にしてカスタマイズします。

  • Step3:
    棒グラフをカスタマイズするときは、 「plotly.express」 のサイトから 「bar」 を選択します。

  • Step4:
    plotly.express.bar」 のWebサイトには、棒グラフを作成するための「bar()」メソッドに指定する引数(プロパティ)の一覧とその説明が掲載されています。 これらの情報をもとに棒グラフをカスタマイズします。
    plotly.express.bar(
        data_frame=None, 
        x=None, y=None, 
        color=None, 
        pattern_shape=None, 
        facet_row=None, facet_col=None, facet_col_wrap=0, facet_row_spacing=None, facet_col_spacing=None, 
        hover_name=None, hover_data=None,     
        custom_data=None, 
        text=None, 
        base=None, 
        error_x=None, error_x_minus=None, error_y=None, error_y_minus=None, 
        animation_frame=None, animation_group=None, 
        category_orders=None, 
        labels=None, 
        color_discrete_sequence=None, color_discrete_map=None, color_continuous_scale=None, 
        pattern_shape_sequence=None, pattern_shape_map=None, 
        range_color=None, 
        color_continuous_midpoint=None, 
        opacity=None, 
        orientation=None, 
        barmode='relative', 
        log_x=False, log_y=False, 
        range_x=None, range_y=None, 
        text_auto=False, 
        title=None, 
        template=None, width=None, height=None
        ) → plotly.graph_objects._figure.Figure  
  • Step5:
    最後に、 「update_traces() 」 「update_layout() 」 「update_annotations() 」 「 update_yaxes()」 「update_xaxes() 」 メソッドを使用して棒グラフの細かい部分をカスタマイズして完了させます。 「update_layout()」メソッドは、 「frames, title, color, tick, hover, legend」などをカスタマイズするときに使用します。
説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[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
click image to zoom!
図N

Plotlyで棒グラフ(Bar Charts)を作成する 【Plotly超入門】

  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のファイルには「リスト19-1」のコードをコピペします。

    click image to zoom!
    図2
    図2は、VS Codeの画面です。
  3. Plotlyのデフォルトのテーマをダークモードに設定する

    ここでは、pioクラスの「templates.defulat」に デフォルトのテーマ「plotly_dark」を設定してダークモードにしています。

    # set a defulat template
    pio.templates.default = 'plotly_dark'
    pio.templates
    click image to zoom!
    図3
    図3では、pioクラスの「templates」に格納されている、Plotlyのテーマの一覧を表示しています。
  4. Plotly Expressでシンプルな棒グラフを作成して見る

    ここでは、Plotly Expressの「bar()」メソッドに引数「x, y」を指定して、 年度別の人口の棒グラフを表示しています。 引数「x」には「year(年度)」、引数「y」には「population(人口)」を指定しています。

    # simple bar chart
    
    year = [1950,1960,1970,1980,1990]
    population = [86459025,95831757,125956499,137065841,147467972]
    
    fig = px.bar(x=year, y=population)
    
    fig.show()
    click image to zoom!
    図4
    図4には、年度別の人口の棒グラフが表示されています。 「x」軸と「y」軸のラベル名は自動的に表示されます。
  5. 棒グラフにタイトルを追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数「title」を追加して 図にタイトルを表示しています。

    # add a title
    title = f"px.bar(df, x=, y=, <b style='color:red'>title='...'</b>)"
    
    fig = px.bar(x=year, y=population,
                 title=title
                 )
    fig.show()
    click image to zoom!
    図5
    図5では、図のタイトルを表示しています。 タイトルにはhtmlのタグも追加することができます。 ここでは、タイトルにhtmlの「<b style='color:red'>...</b>」を追加しています。
  6. Plotlyのデフォルトのテーマを変更する

    ここでは、Plotly Expressの「bar()」メソッドに引数「template」を追加して テーマを「seaborn」に変えています。

    # add a template (theme)
    add = "template='seaborn'"
    title = f"px.bar(df, x=, y=, <b style='color:red'>{add}</b>)"
    
    fig = px.bar(x=year, y=population,
                 template='seaborn,  
                 title=title                
                 )
    fig.show()
    click image to zoom!
    図6
    図6には、「seaborn」のテーマが表示されています。 図の背景色がダークモードから「白+灰色」に変わっています。
  7. Plotly ExpressのgapminderデータをPandasのDataFrameに取り込む

    ここでは、Plotly Expressが用意している「gapminder」データを PandasのDataFrameに取り込んで後述するステップで利用します。

    raw_df = px.data.gapminder()
    # raw_df.info()
    # raw_df['continent'].unique()
    # len(raw_df['country'].unique().tolist())     
    asia_df = raw_df.query("continent=='Asia'")
    # asia_df['country'].unique()
    japan_df = raw_df.query("country=='Japan'")
    # japan_df  
    click image to zoom!
    図7-1
    図7-1では、「px.data.gapminder()」メソッドで 世界の各種データをPandasのDataFrameに取り込んでいます。 DataFrameは「country, continent, year, lifeExp, pop, gdpPercap,...」などのカラムから構成されています。 「country」には「国名」、 「continent」には「大陸名」、「year」には「年度」、 「lifeExp」には「平均寿命」、「pop」には「人口」、 「gdpPercap」には「一人当たりの国内総生産]が格納されています。

    click image to zoom!
    図7-2
    図7-2では、DataFrameのカラム「continent, country」の内容を表示しています。 「continent」には「Asia, Europe, Africa, Americas, Oceania」が格納されています。 「country」には、142カ国の国名が格納されています。 アジアには「日本、中国、インド、...」等が含まれます。

    click image to zoom!
    図7-3
    図7-3には、日本のデータを表示しています。 DataFrameには「1952~2007」のデータが格納されています。
  8. Plotly Expressの「bar()」メソッドに引数「color」を追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数「color」を追加して 棒グラフを年度ごとに色分けするようにしています。 つまり、カラーマップを使用するようにします。

    # bar chart : add a color
    add = "color='year'"
    title = f"px.bar(df, x=, y=, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("country=='Japan'")
    
    fig = px.bar(df, 
                 x='year', y='pop', 
                 color='year',
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図8
    図8には、年度別の日本の人口がカラーマップされて表示されています。 カラーマップを使うと、データの値に応じて色を割り当てることができます。 ここでは、DataFrameの「query()」メソッドで日本のデータのみ抽出しています。
  9. Plotly Expressの「bar()」メソッドに引数「labels」を追加する

    ここでは、Plotly Exressの「bar()」メソッドに引数「labels」を追加して、 X軸、Y軸のラベル名と凡例を分かりやすくしています。

    # bar chart : add a labels
    add = "labels=dict(year='Year', pop='Population')"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("country=='Japan'")
    
    fig = px.bar(df, 
                 x='year', y='pop', 
                 color='year',
                 labels=dict(year='Year', pop='Population'),
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図9
    図9では、X軸、Y軸のラベル名がDataFrameのカラム名「year, pop」から 「Year, Population」に変わっています。 凡例も「year」から「Year」に変わっています。
  10. Plotly Expressの「bar()」メソッドに引数「hover_name, hover_data」を追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数「hover_name, hover_data」を追加して ホバーテキストに「国名」と「平均寿命」を表示させます。

    # bar chart : Asia top 6 + hove_name, hover_data
    add = "hover_name='country', hover_data=['lifeExp']"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2007") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    
    fig = px.bar(df, 
                 x='country', y='pop', 
                 color='country',
                 hover_name='country',
                 hover_data=['lifeExp'],
                 labels=dict(country='Country', pop='Population', lifeExp='Life Expectancy'),
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図10
    図10では、ホバーテキストに「国名、人口、平均寿命」が表示されています。 X軸の「国名」とY軸の「人口」は自動的に表示されます。
  11. Plotly Expressの「bar()」メソッドに引数「custom_data」を追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数「custom_data」を追加して ホバーテキストに「rank(ランク」」も表示させます。

    ホバーテキストに「x, y」以外のデータを表示させるには、 「custom_data」にDataFrameのカラム名「rank」を指定します。 ホバーテキストをカスタマイズするには、 figureクラスの「update_traces()」メソッドに引数「hovertemplate」を追加します。

    # bar chart : Asia top 6 + custom_data, traces(hovertemplate)
    add = "custom_data=['rank']"
    traces = "hovertemplate=..."
    title = f"px.bar(, <b style='color:red'>{add}</b>) + update_traces(<b style='color:red'>{traces}</b>)"
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2007") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='country', y='pop', 
                 color='country',
                 custom_data=['rank'],
                 labels=dict(country='Country', pop='Population'),
                 title=title   
                 )
    
    fig.update_traces(  
            hovertemplate="%{label}<br><br>Rank: %{customdata}<br>Population: %{value}"
    )
    
    fig.show()
    click image to zoom!
    図11
    図11では、カスタマイズされたホバーテキスト「国名、ランク、人口」が表示されています。
  12. Plotly Expressの「bar()」メソッドに引数「text_auto, text」を追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数「text_auto, text」を追加して 棒グラフにテキスト文字を表示させます。

    # 1: bar chart : text_auto=True
    add = "text_auto=True"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = (raw_df['country'].isin(['Japan','China','India'])) & \
                     (raw_df['year'] > 1990)
    df = raw_df[filter_country]
    df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 text_auto=True,
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    # %%
    
    # 2: bar chart : text='country'
    add = "text='country'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = (raw_df['country'].isin(['Japan','China','India'])) & \
                     (raw_df['year'] > 1990)
    df = raw_df[filter_country]
    df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 text='country',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    # %%
        
    # 3: bar chart : text_auto + textposition=inside)
    add = "text_auto='.2s'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("continent == 'Asia' and year == 2007 and pop > 70.e6")
    df = df.sort_values('pop', ascending=False).reset_index(drop=True)
    df
    fig = px.bar(df, 
                 x='country', y='pop',             
                 color='country',
                 text_auto='.2s',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    # %%
    
    # 4: bar chart : text_auto + update_traces(textposition=outside)
    add = "text_auto='.2s'"
    traces = "textposition='outside'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + update_traces(<b style='color:red'>{traces}</b>)"
    
    
    df = raw_df.query("continent == 'Asia' and year == 2007 and pop > 70.e6")
    df = df.sort_values('pop', ascending=False).reset_index(drop=True)
    df
    
    fig = px.bar(df, 
                 x='country', y='pop',             
                 color='country',
                 text_auto='.2s',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.update_traces(textfont_size=12, textangle=0, textposition='outside', cliponaxis=False)
    
    fig.show()
    click image to zoom!
    図12-1
    図12-1では、「bar()」メソッドの引数に「text_auto=True」を追加して 棒グラフに「人口」を表示させています。 数値の桁数が多いときは自動的に短縮されます。 「M, B」は「Million(百万), Billion(十億)」を意味します。

    click image to zoom!
    図12-2
    図12-2では、「bar()」メソッドの引数に「text='country'」を追加して 棒グラフに「国名」を表示させています。

    click image to zoom!
    図12-3
    図12-3では、「bar()」メソッドの引数に「text_auto='.2s'」を追加して 棒グラフに「人口」をフォーマットして表示させています。 「.2s」は「SI prefix notaion」を使用するように指示しています。 この場合「1,200,000」が「1.2M」のように短縮されて表示されます。

    click image to zoom!
    図12-4
    図12-4では、figureの「update_traces()」メソッドに引数「textposition='outside'」を追加して テキスト文字を棒グラフの外に表示させています。 テキスト文字を斜めに表示させたいときは「textangle=-45」にします。
  13. Plotly Expressの「bar()」メソッドに引数「barmode」を追加する

    Plotly Expressの「bar()」メソッドに引数「barmode」を追加して 棒グラフを「relative, group, overlay」形式で表示させます。

    # 1: bar chart : barmode=relative
    add = "barmode='relative'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 barmode='relative',   # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    # %%
    
    # 2: bar chart : barmode=group
    add = "barmode='group'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 barmode='group',   # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    # %%
    
    # 3: bar chart : barmode=overlay
    add = "barmode='overlay'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 barmode='overlay',   # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図13-1
    図13-1では、棒グラフを「relative」モードで表示させています。

    click image to zoom!
    図13-2
    図13-2では、棒グラフを「group」モードで表示させています。

    click image to zoom!
    図13-3
    図13-3では、棒グラフを「overlay」モードで表示させています。
  14. Plotly Expressの「bar()」メソッドに引数「orientation」を追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数「orientation」を追加して 棒グラフを水平型(horizontal)で表示させます。

    # bar chart : Basic Horizontal Bar Chart
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図14
    図14では、棒グラフを水平型で表示させています。 引数「orientation=」に「h」を指定すると水平型、 「v」を指定すると垂直型の棒グラフになります。
  15. figureの「update_layout()」メソッドに「xaxis_tickangle=-45」を追加する

    ここでは、figureクラスの「update_layout()」メソッドに 「xaxis_tickangle=-45」を追加してX軸のラベルを斜めに表示させます。

    # bar chart : Rotated Bar Chart Labels
    add = ""
    layout="xaxis_tickangle=-45"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + update_layout(<b style='color:red'>{layout}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.update_layout(xaxis_tickangle=-45)
    
    fig.show()
    click image to zoom!
    図15
    図15には、X軸のラベルが斜めに表示されています。
  16. Plotly Expressの「bar()」メソッドに引数「pattern_shape, pattern_shape_sequence」を追加する

    ここでは、Plotly Expressの「bar()」メソッドに引数 「pattern_shape, pattern_shape_sequence」を追加して棒グラフ内を特定のパターンにします。

    # bar chart : Pattern Fills
    add = "pattern_shape='country', pattern_shape_sequence=['.', 'x', '+']"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = (raw_df['country'].isin(['Japan','China','India'])) & \
                     (raw_df['year'] > 1990)
    df = raw_df[filter_country]
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 pattern_shape='country', pattern_shape_sequence=['.', 'x', '+'],             
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図16
    図16では、棒グラフ内が特定のパターン「.」「x」「*」で分離されています。
  17. Plotly Expressの「bar()」メソッドに引数「color=continent」を追加する

    ここでは、棒グラフの凡例(国名)をクリックして棒グラフを図から削除したり復活させます。

    # bar chart : color=continent : toggle continent(America, Asia, Europe)
    add = "color='continent'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>toggle continent(America, Asia, Europe)</b>"
    
    df = raw_df.groupby(['year','continent']) \
        .agg({
            'lifeExp': 'last',
            'pop': 'sum',
            'gdpPercap': 'sum'
        }).reset_index()
    
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='continent',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    click image to zoom!
    図17-1
    図17-1では、棒グラフに「Africa, Americas, Asia, Europe」の4地域しか表示されていません。 「Oceania」の人口はあまりにも少ないので棒グラフには表示されません。
    click image to zoom!
    図17-2
    図17-2では、凡例から「Americas, Asia, Europe」をクリックして棒グラフを削除しています。 この場合、棒グラフには「Oceania」も表示されます。
  18. 水平形の棒グラフに人口の上位・下位10位の国を表示する

    ここでは、PandasのDataFrameの「nlargest()」メソッドを使用して 世界の人口から上位10位までの棒グラフを表示させます。 また、「nsmallest()」メソッドを使用して 世界の人口から下位10までの棒グラフを表示させます。

    # 1: Horizontal Bar Chart: top / bottom N populations in the world
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 10 populations in the world</b>"
    
    df = raw_df.query("year==2007") \
            .nlargest(10, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    # %%
    
    # 2: Horizontal Bar Chart: top / bottom N populations + add_annotation()
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>add_annotation(📍)</b>"
    
    df = raw_df.query("year==2007") \
            .nlargest(10, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.add_annotation(
                text=' 📍         ',   
                y='Japan',
                showarrow=False
                )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    # %%
    
    # 3: Horizontal Bar Chart: op / bottom N  lifeExp + texttemplate='Rank: %{customdata}' 
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Bottom 10 Life Expectancy in the World in 2007</b>"
    
    df = raw_df.query("year==2007") \
            .nsmallest(10, 'lifeExp')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='lifeExp', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title                 
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    click image to zoom!
    図18-1
    図18-1では、世界の人口の上位10位までの棒グラフを表示させています。 1位は中国、2位はインド、3位はアメリカになっています。 日本は9位になっています。 ちなみに、この順位は2007年のデータです。

    click image to zoom!
    図18-2
    図18-2では、日本の棒グラフに注釈の「📍」を表示させています。

    click image to zoom!
    図18-3
    図18-3では、平均寿命の下位10位を棒グラフに表示させています。 下位1位は南アフリカのスワジランド王国です。 なんと平均寿命が約39歳になっています。 ちなみにこの平均寿命は2007年のデータです。
  19. 水平形の棒グラフに人口の上位・下位「N%」の国を表示する

    ここでは、PandasのDataFrameの「quantile()」メソッドを使用して 世界の人口の「N%」の棒グラフを表示させます。 たとえば、上位10%の棒グラフを作成するには「quantile(0.90)」、 下位10%の棒グラフを作成するには「quantile(0.10)」のようにパーセントを指定します。

    # 1: Horizontal Bar Chart: pop top 5% 
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 5% Population in the World in 2007</b>"
    
    df = raw_df.query("year==2007")[['country','pop']] 
    top_5p = df.set_index('country').quantile(0.95)   
    filter = f"pop >= {top_5p.values[0]}" # pop >= 99999
    df = raw_df.query("year==2007") \
        .query(filter)
    df = df.sort_values('pop', ascending=False).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title   
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    # %%
    
    # 2: Horizontal Bar Chart: gdpPercap top 15% 
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 15% GDP per Capita in the World in 2007</b>"
    
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007")[['country','gdpPercap']] 
    top_15p = df.set_index('country').quantile(0.85)   
    filter = f"gdpPercap >= {top_15p.values[0]}" # gdpPercap >= 99999
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007") \
        .query(filter)
    df = df.sort_values('gdpPercap', ascending=False).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='gdpPercap', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', gdpPercap='GDP per Capita'),
                 title=title                
                 )
    
    fig.add_annotation(
                text=' 📍            ',   
                y='Japan',
                showarrow=False
                )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    # %%
    
    # 3: Horizontal Bar Chart: lifeExp top 5% + annotation
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 5% Life Expectancy in the World in 2007</b>"
    
    df = raw_df.query("year==2007")[['country','lifeExp']] 
    top_5p = df.set_index('country').quantile(0.95)   
    filter = f"lifeExp >= {top_5p.values[0]}" # lifeExp >= 99999
    df = raw_df.query("year==2007") \
        .query(filter)
    df = df.sort_values('lifeExp', ascending=False).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='lifeExp', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title   
                 )
    
    fig.add_annotation(
                text=' 📍            ',  
                y='Japan',
                showarrow=False
                )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    # %%
    
    # 4: Horizontal Bar Chart: lifeExp bottom 20% + annotation
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Bottom 20% Life Expectancy in the World in 2007</b>"
    
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007")[['country','lifeExp']] 
    bottom_20p = df.set_index('country').quantile(0.20)   
    filter = f"lifeExp <= {bottom_20p.values[0]}" # lifeExp <= 99999
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007") \
        .query(filter)
    df = df.sort_values('lifeExp', ascending=True).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='lifeExp', y='country',
                 color='country',
                 custom_data=['rank'],
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title    
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Life Expectancy(%{x}), Rank(%{customdata})'     
    )
    
    fig.show()
    click image to zoom!
    図19-1
    図19-1では、世界の人口の上位5%の棒グラフを作成しています。 上位5%には、8カ国が含まれます。

    click image to zoom!
    図19-2
    図19-2では、世界の一人当たりのGDPの上位15%の棒グラフを作成しています。 上位15%には5カ国が含まれます。 日本は4位になっています。 日本の棒グラフには注釈の「📍」が表示されています。

    click image to zoom!
    図19-3
    図19-3では、世界の平均寿命の上位5%の棒グラフを作成しています。 上位5%には8カ国が含まれます。 日本は1位になっています。 このデータは2007年のデータです。

    click image to zoom!
    図19-4
    図19-4では、世界の平均寿命の下位20%の棒グラフを作成しています。 下位20%には7カ国が含まれます。 下位1位は、アフガニスタンで平均寿命は「約43歳」になっています。 このデータは2007年のデータです。
  20. 全てのコードを掲載

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

    リスト19-1: Article146.py
    # Article145 Plotly Bar Charts v20.py
    # %%
    
    ### import the libraries
    import numpy as np
    import pandas as pd
    
    import plotly.io as pio
    import plotly.express as px
    import plotly.graph_objects as go
    
    
    # %%
    
    '''
    plotly.express.bar(
        data_frame=None, 
        x=None, y=None, 
        color=None, 
        pattern_shape=None, ★
        facet_row=None, facet_col=None, facet_col_wrap=0, 
        facet_row_spacing=None, facet_col_spacing=None, 
        hover_name=None, hover_data=None, custom_data=None, ★
        text=None, ★
        base=None, 
        error_x=None, error_x_minus=None, 
        error_y=None, error_y_minus=None, 
        animation_frame=None, animation_group=None, 
        category_orders=None, 
        labels=None, ★
        color_discrete_sequence=None, color_discrete_map=None, color_continuous_scale=None, 
        pattern_shape_sequence=None, pattern_shape_map=None, 
        range_color=None, 
        color_continuous_midpoint=None, 
        opacity=None, 
        orientation=None, ★ 'h' for horizontal 'v' for vertical
        barmode='relative', ★ 'relative', 'group', 'overlay'
        log_x=False, log_y=False, 
        range_x=None, range_y=None, 
        text_auto=False, ★
        title=None, ★
        template=None, ★ 
        width=None, height=None) 
        → plotly.graph_objects._figure.Figure
    '''
    
    # %%
    
    # 1: set a defulat template
    pio.templates.default = 'plotly_dark'
    pio.templates
    
    
    # %%
    
    # 2: simple bar chart
    add = "Simple Bar Chart"
    text = f"px.bar(x=year, y=population): <b style='color:red'>{add}</b>"
    
    year = [1950,1960,1970,1980,1990]
    population = [86459025,95831757,125956499,137065841,147467972]
    
    fig = px.bar(x=year, y=population)
    
    fig.add_annotation(text=text, 
                       xref="paper", yref="paper",
                       x=0.0, y=1.1, 
                       showarrow=False)
    
    fig.show()
    
    
    # %%
    
    # 3: add a title
    title = f"px.bar(df, x=, y=, <b style='color:red'>title='...'</b>)"
    
    fig = px.bar(x=year, y=population,
                 title=title
                 )
    fig.show()
    
    
    # %%
    
    # 4: add a template (theme)
    add = "template='seaborn'"
    title = f"px.bar(df, x=, y=, <b style='color:red'>{add}</b>)"
    
    fig = px.bar(x=year, y=population,
                 template='seaborn',  
                 title=title                
                 )
    fig.show()
    
    
    # %%
    
    # 5: load data from plotly express gapminder()
    raw_df = px.data.gapminder()
    # raw_df.info()
    #  #   Column     Non-Null Count  Dtype  
    # ---  ------     --------------  -----  
    #  0   country    1704 non-null   object 
    #  1   continent  1704 non-null   object 
    #  2   year       1704 non-null   int64  
    #  3   lifeExp    1704 non-null   float64
    #  4   pop        1704 non-null   int64  
    #  5   gdpPercap  1704 non-null   float64
    #  6   iso_alpha  1704 non-null   object 
    #  7   iso_num    1704 non-null   int64 
    
    # raw_df
    #       country	continent	year	lifeExp	pop	        gdpPercap	iso_alpha	iso_num
    # 0	    Afghanistan	Asia	1952	28.801	8425333	    779.445314	AFG	        4
    # 1	    Afghanistan	Asia	1957	30.332	9240934	    820.853030	AFG	        4
    # 2	    Afghanistan	Asia	1962	31.997	10267083	853.100710	AFG	        4
    # 3	    Afghanistan	Asia	1967	34.020	11537966	836.197138	AFG	        4
    # 4	    Afghanistan	Asia	1972	36.088	13079460	739.981106	AFG	        4
    # ...	...	...	...	...	...	...	...	...
    # 1699	Zimbabwe	Africa	1987	62.351	9216418	    706.157306	ZWE	        716
    # 1700	Zimbabwe	Africa	1992	60.377	10704340	693.420786	ZWE	        716
    # 1701	Zimbabwe	Africa	1997	46.809	11404948	792.449960	ZWE	        716
    # 1702	Zimbabwe	Africa	2002	39.989	11926563	672.038623	ZWE	        716
    # 1703	Zimbabwe	Africa	2007	43.487	12311143	469.709298	ZWE	        716
    
    # raw_df['continent'].unique()
    df = raw_df.query("continent=='Asia'")
    # df['country'].unique()
    # array(['Afghanistan', 'Bahrain', 'Bangladesh', 'Cambodia', 'China',
    #        'Hong Kong, China', 'India', 'Indonesia', 'Iran', 'Iraq', 'Israel',
    #        'Japan', 'Jordan', 'Korea, Dem. Rep.', 'Korea, Rep.', 'Kuwait',
    #        'Lebanon', 'Malaysia', 'Mongolia', 'Myanmar', 'Nepal', 'Oman',
    #        'Pakistan', 'Philippines', 'Saudi Arabia', 'Singapore',
    #        'Sri Lanka', 'Syria', 'Taiwan', 'Thailand', 'Vietnam',
    #        'West Bank and Gaza', 'Yemen, Rep.'], dtype=object)
    
    # len(df['country'].unique().tolist())  # 33   
    
    df = raw_df.query("country=='Japan'")
    df
    #       country	continent	year	lifeExp	pop	        gdpPercap	    iso_alpha	iso_num
    # 792	Japan	Asia	    1952	63.030	86459025	3216.956347	    JPN	        392
    # 793	Japan	Asia	    1957	65.500	91563009	4317.694365	    JPN	        392
    # 794	Japan	Asia	    1962	68.730	95831757	6576.649461	    JPN	        392
    # 795	Japan	Asia	    1967	71.430	100825279	9847.788607	    JPN	        392
    # 796	Japan	Asia	    1972	73.420	107188273	14778.786360	JPN	        392
    # 797	Japan	Asia	    1977	75.380	113872473	16610.377010	JPN	        392
    # 798	Japan	Asia	    1982	77.110	118454974	19384.105710	JPN	        392
    # 799	Japan	Asia	    1987	78.670	122091325	22375.941890	JPN	        392
    # 800	Japan	Asia	    1992	79.360	124329269	26824.895110	JPN	        392
    # 801	Japan	Asia	    1997	80.690	125956499	28816.584990	JPN	        392
    # 802	Japan	Asia	    2002	82.000	127065841	28604.591900	JPN	        392
    # 803	Japan	Asia	    2007	82.603	127467972	31656.068060	JPN	        392
    
    
    # %%
    
    # 6: bar chart : add a color
    add = "color='year'"
    title = f"px.bar(df, x=, y=, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("country=='Japan'")
    
    fig = px.bar(df, 
                 x='year', y='pop', 
                 color='year',
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 7: bar chart : add a labels
    add = "labels=dict(year='Year', pop='Population')"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("country=='Japan'")
    
    fig = px.bar(df, 
                 x='year', y='pop', 
                 color='year',
                 labels=dict(year='Year', pop='Population'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 8: bar chart : Asia top 6 + hove_name, hover_data
    # https://plotly.com/python/hover-text-and-formatting/
    
    add = "hover_name='country', hover_data=['lifeExp']"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2007") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    
    fig = px.bar(df, 
                 x='country', y='pop', 
                 color='country',
                 hover_name='country',
                 hover_data=['lifeExp'],
                 labels=dict(country='Country', pop='Population', lifeExp='Life Expectancy'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 9: bar chart : Asia top 6 + custom_data, traces(hovertemplate)
    add = "custom_data=['rank']"
    traces = "hovertemplate=..."
    title = f"px.bar(, <b style='color:red'>{add}</b>) + update_traces(<b style='color:red'>{traces}</b>)"
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2007") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.bar(df, 
                 x='country', y='pop', 
                 color='country',
                 custom_data=['rank'],
                 labels=dict(country='Country', pop='Population'),
                 title=title   
                 )
    
    fig.update_traces(  
            hovertemplate="%{label}<br><br>Rank: %{customdata}<br>Population: %{value}"
    )
    
    fig.show()
    
    
    # %%
    
    # 10-1: bar chart : text_auto=True
    add = "text_auto=True"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = (raw_df['country'].isin(['Japan','China','India'])) & \
                     (raw_df['year'] > 1990)
    df = raw_df[filter_country]
    df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 text_auto=True,
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 10-2: bar chart : text='country'
    add = "text='country'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = (raw_df['country'].isin(['Japan','China','India'])) & \
                     (raw_df['year'] > 1990)
    df = raw_df[filter_country]
    df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 text='country',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 10-3: bar chart : text_auto + textposition=inside)
    add = "text_auto='.2s'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    df = raw_df.query("continent == 'Asia' and year == 2007 and pop > 70.e6")
    # df = raw_df.query("continent == 'Asia' and year == 2007 and pop > 2.e6")
    df = df.sort_values('pop', ascending=False).reset_index(drop=True)
    df
    fig = px.bar(df, 
                 x='country', y='pop',             
                 color='country',
                 text_auto='.2s',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 10-4: bar chart : text_auto + update_traces(textposition=outside)
    add = "text_auto='.2s'"
    traces = "textposition='outside'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + update_traces(<b style='color:red'>{traces}</b>)"
    
    
    df = raw_df.query("continent == 'Asia' and year == 2007 and pop > 70.e6")
    # df = raw_df.query("continent == 'Asia' and year == 2007 and pop > 2.e6")
    df = df.sort_values('pop', ascending=False).reset_index(drop=True)
    df
    
    fig = px.bar(df, 
                 x='country', y='pop',             
                 color='country',
                 text_auto='.2s',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.update_traces(textfont_size=12, textangle=0, textposition='outside', cliponaxis=False)
    
    fig.show()
    
    
    # %%
    
    # 11-1: bar chart : barmode=relative
    add = "barmode='relative'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 barmode='relative',   # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    # %%
    
    # 11-2: bar chart : barmode=group
    add = "barmode='group'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 barmode='group',   # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 11-3: bar chart : barmode=overlay
    add = "barmode='overlay'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 barmode='overlay',   # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 12: bar chart : Basic Horizontal Bar Chart
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 13: bar chart : Rotated Bar Chart Labels
    add = ""
    layout="xaxis_tickangle=-45"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + update_layout(<b style='color:red'>{layout}</b>)"
    
    filter_country = raw_df['country'].isin(['Japan','China','India'])
    df = raw_df[filter_country]
    # df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 # barmode='relative', # relative(default), group, overlay
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.update_layout(xaxis_tickangle=-45)
    
    fig.show()
    
    
    # %%
    
    # 14: bar chart : Pattern Fills
    add = "pattern_shape='country', pattern_shape_sequence=['.', 'x', '+']"
    title = f"px.bar(, <b style='color:red'>{add}</b>)"
    
    filter_country = (raw_df['country'].isin(['Japan','China','India'])) & \
                     (raw_df['year'] > 1990)
    df = raw_df[filter_country]
    df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='country',
                 pattern_shape='country', pattern_shape_sequence=['.', 'x', '+'],             
                 # text='country',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    
    # %%
    
    # 15: bar chart : color=continent : toggle continent(America, Asia, Europe)
    add = "color='continent'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>toggle continent(America, Asia, Europe)</b>"
    
    df = raw_df.groupby(['year','continent']) \
        .agg({
            'lifeExp': 'last',
            'pop': 'sum',
            'gdpPercap': 'sum'
        }).reset_index()
    
    df
    fig = px.bar(df, 
                 x='year', y='pop',
                 color='continent',
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.show()
    
    
    # %%
    
    # 16-1: Horizontal Bar Chart: top / bottom N populations in the world
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 10 populations in the world</b>"
    
    df = raw_df.query("year==2007") \
            .nlargest(10, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    
    
    # %%
    
    # 16-2: Horizontal Bar Chart: top / bottom N populations + add_annotation()
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>add_annotation(📍)</b>"
    
    df = raw_df.query("year==2007") \
            .nlargest(10, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country'),
                 title=title   
                 # title='Top 10 Most Populated Countries in the World in 2007'
                 )
    
    fig.add_annotation(
                text=' 📍         ',  # 🎌 📌 📍  
                # text='  ▶         ',  # 🎌
                y='Japan',
                showarrow=False
                )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    
    # %%
    
    # 16-3: Horizontal Bar Chart: op / bottom N  lifeExp + texttemplate='Rank: %{customdata}' 
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Bottom 10 Life Expectancy in the World in 2007</b>"
    
    df = raw_df.query("year==2007") \
            .nsmallest(10, 'lifeExp')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='lifeExp', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title              
                 # title='Bottom 10 Life Expectancy in the World in 2007'   
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    
    # %%
    
    # 17-1: Horizontal Bar Chart: pop top 5% 
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 5% Population in the World in 2007</b>"
    
    df = raw_df.query("year==2007")[['country','pop']] 
    top_5p = df.set_index('country').quantile(0.95)   
    filter = f"pop >= {top_5p.values[0]}" # pop >= 99999
    df = raw_df.query("year==2007") \
        .query(filter)
    df = df.sort_values('pop', ascending=False).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='pop', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title
                 # title='Top 5% Population in the World in 2007'   
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    
    # %%
    
    # 17-2: Horizontal Bar Chart: gdpPercap top 15% 
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 15% GDP per Capita in the World in 2007</b>"
    
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007")[['country','gdpPercap']] 
    top_15p = df.set_index('country').quantile(0.85)   
    filter = f"gdpPercap >= {top_15p.values[0]}" # gdpPercap >= 99999
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007") \
        .query(filter)
    df = df.sort_values('gdpPercap', ascending=False).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='gdpPercap', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', gdpPercap='GDP per Capita'),
                 title=title             
                 # title='Top 15% GDP per Capita in the World in 2007'   
                 )
    
    fig.add_annotation(
                text=' 📍            ',  # 🎌 📌 📍  
                # text='  ▶         ',  # 🎌
                y='Japan',
                showarrow=False
                )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    
    # %%
    
    
    # 17-3: Horizontal Bar Chart: lifeExp top 5% + annotation
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Top 5% Life Expectancy in the World in 2007</b>"
    
    df = raw_df.query("year==2007")[['country','lifeExp']] 
    top_5p = df.set_index('country').quantile(0.95)   
    filter = f"lifeExp >= {top_5p.values[0]}" # lifeExp >= 99999
    df = raw_df.query("year==2007") \
        .query(filter)
    df = df.sort_values('lifeExp', ascending=False).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='lifeExp', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title 
                 # title='Top 5% Life Expectancy in the World in 2007'   
                 )
    
    fig.add_annotation(
                text=' 📍            ',  # 🎌 📌 📍  
                # text='  ▶         ',  # 🎌
                y='Japan',
                showarrow=False
                )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Rank: %{customdata}'     
    )
    
    fig.show()
    
    
    # %%
    
    # 17-4: Horizontal Bar Chart: lifeExp bottom 20% + annotation
    add = "orientation='h'"
    title = f"px.bar(, <b style='color:red'>{add}</b>) + <b style='color:red'>Bottom 20% Life Expectancy in the World in 2007</b>"
    
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007")[['country','lifeExp']] 
    bottom_20p = df.set_index('country').quantile(0.20)   
    filter = f"lifeExp <= {bottom_20p.values[0]}" # lifeExp <= 99999
    df = raw_df.query("continent=='Asia'") \
        .query("year==2007") \
        .query(filter)
    df = df.sort_values('lifeExp', ascending=True).reset_index(drop=True) 
    df['rank'] = df.index+1
    
    # df
    fig = px.bar(df, 
                 x='lifeExp', y='country',
                 color='country',
                 custom_data=['rank'],
                 # barmode='overlay', # relative(default), group, overlay
                 orientation='h',   # h-horizontal, v-vertical
                 labels=dict(year='Year', pop='Population', country='Country', lifeExp='Life Expectancy'),
                 title=title  
                 # title='Bottom 20% Life Expectancy in the World in 2007'   
                 )
    
    fig.update_traces(
            textposition='inside', 
            texttemplate='Life Expectancy(%{x}), Rank(%{customdata})'     
    )
    
    fig.show()