Python {Article145}

ようこそ「Python」へ...

Python: Plotlyで円グラフ(pie charts)を作成する (Plotly Express, Plotly Graph Objects【Plotly超入門】

ここでは、Plotlyを使用して円グラフ(pie 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」などに分類されています。 たとえば、今回のように円グラフを作成したいときは、 「Pie Charts」を選択します。

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

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

  • Step4:
    plotly.express.pie」 のWebサイトには、円グラフを作成するための「pie()」メソッドに指定する引数の一覧とその説明が掲載されています。 これらの情報をもとに円グラフをカスタマイズします。
    plotly.express.pie(
        data_frame=None, names=None, values=None, color=None, 
        facet_row=None, facet_col=None, facet_col_wrap=0, 
        facet_row_spacing=None, facet_col_spacing=None, 
        color_discrete_sequence=None, color_discrete_map=None, 
        hover_name=None, hover_data=None, 
        custom_data=None, category_orders=None, labels=None, title=None, 
        template=None, width=None, height=None, opacity=None, hole=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 Pie simple
click image to zoom!
図B Pie pull
click image to zoom!
図C Pie hover
click image to zoom!
図D Pie hole
click image to zoom!
図E Pie texttemplate
click image to zoom!
図F Pie hovertemplate

click image to zoom!
図G Pie pull

Plotly Expressで円グラフ(pie 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のファイルには「リスト13-1」のコードをコピペします。

    click image to zoom!
    図2
    図2は、VS Codeの画面です。
  3. まずは、Plotly Expressでシンプルな円グラフを作成して見る

    ここでは、中国、インド、インドネシア、日本の人口の円グラフを作成します。 Plotly Expressで円グラフを作成するには「pie()」メソッドを使用します。 引数「names」には国名リストの変数名「country」、引数「values」には人口リストの変数名「population」を指定しています。 これで人口の円グラフが作成されます。国別のパーセント(%)は自動的に表示されます。

    ここでは、さらに円グラフにタイトル、テーマなどを追加していきます。 以下、解説は図の説明で行います。

    ### 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.pie(
            data_frame=None, 
            names=None, values=None, 
            color=None, 
            facet_row=None, facet_col=None, 
            facet_col_wrap=0, facet_row_spacing=None, facet_col_spacing=None, 
            color_discrete_sequence=None, color_discrete_map=None, 
            hover_name=None, hover_data=None, 
            custom_data=None, 
            category_orders=None, 
            labels=None, 
            title=None, 
            template=None, 
            width=None, height=None, 
            opacity=None, hole=None) 
            → plotly.graph_objects._figure.Figure
    '''
    
    # simple pie chart
    country = ['China', 'India', 'Indonesia', 'Japan']
    population = [1280400000, 1034172547, 211060000, 127065841]
    
    fig = px.pie(names=country, values=population)
    
    fig.show()
    
    # %%
    
    # add a title
    
    fig = px.pie(names=country, values=population,
                 title='px pie(names=country, values=population, title=...)'
                 )
    fig.show()
    
    
    # %%
    
    # add a template (theme)
    
    fig = px.pie(names=country, values=population,
                 template='plotly_dark',  
                 title='px pie(names=, values=, template=plotly_dark)'                
                 )
    fig.show()
    
    # set a default template
    
    pio.templates.default = 'plotly_dark'
    # pio.templates.default = 'plotly_white'
    
    fig = px.pie(names=country, values=population,    
                 title='px pie(...): pio.templates.default=plotly_dark'            
                 )
    fig.show()
    
    # %%     
    click image to zoom!
    図3-1
    図3-1には、シンプルな4カ国の人口の円グラフが表示されています。 円グラフのパーセント(%)は、自動的に表示されます。 円グラフにマウスをホバリングさせると、ホバーテキスト「国名、人口」が表示されます。 このように、Plotlyではデフォルトの状態でインタラクティブ機能が有効になっています。

    click image to zoom!
    図3-2
    図3-2では、凡例から国名「Indonesia」をクリックして円グラフを削除しています。 円グラフから削除されると凡例がグレーアウトされます。 再度「Indonesia」をクリックすると円グラフに追加されます。
    click image to zoom!
    図3-3
    図3-3では、Plotly Expressの「pie()」メソッドに引数「title」を追加して円グラフのタイトルを表示しています。

    click image to zoom!
    図3-4
    図3-4では、Plotly Expressの「pie()」メソッドに引数「template」を追加して円グラフのテーマを設定しています。 ここではダークモードの「plotly_dark」を設定しています。

    click image to zoom!
    図3-5
    図3-5では、Plotly Expressの「pie()」メソッドではなく、 pioクラスの「templates.default」にテーマ「plotly_dark」を設定しています。 この場合、Plotly Expressの全てのグラフがダークモードで表示されるようになります。 「templates.default」の初期値は「plotly_white」になっています。
  4. Plotly ExpressのgapminderデータをPandasのDataFrameに取り込む

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

    # load data from plotly express gapminder()
    raw_df = px.data.gapminder()
    # raw_df.info()
    # raw_df
    # raw_df['continent'].unique()
    df = raw_df.query("continent=='Asia'")
    # df['country'].unique()
    # len(df['country'].unique().tolist())   
    click image to zoom!
    図4-1
    図4-1では、「px.data.gapminder()」メソッドで世界の人口データ等をPandasのDataFrameに取り込んでいます。 DataFrameは「country, continent, year, lifeExp, pop, gdpPercap,...」などのカラムから構成されています。

    「country」には「国名」、 「continent」には「大陸名」、「year」には「年度」、「lifeExp」には「平均寿命」、「pop」には「人口」、 「gdpPercap」には「一人当たりの国内総生産]が格納されています。

    click image to zoom!
    図4-2
    図4-2では、アジアの国名と件数を表示しています。 DataFrameには33カ国のアジアの国名が登録されています。
  5. PandasのDataFrameから「アジア」の国々を絞り込んで人口の上位6位までを円グラフに表示する

    ここでは、アジアの人口上位6位までの国とその他を円グラフにします。 7位以下の国は「Other countries(その他)」として表示します。

    DataFrameから「アジア」の「2002」年のデータを絞り込むのに「query()」メソッドを使用しています。 人口が上位6位までの国を絞り込むには「nlargest()」メソッドを使用します。 7位以下の国々を「その他」としてまとめるには、 DataFrameのカラム「country(国名)」を「other countries」に書き換えます。 そして、DataFrameの「groupby().agg(sum)」メソッドで人口を再計算します。

    # pie chart : Asia top 6 + others
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    pop_min = df['pop'].min()
    # pop_min
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002")      
    df.loc[df['pop'] < pop_min, 'country'] = 'Other countries' # Represent only large countries
    df = df.groupby('country').agg(sum)
    df.reset_index(inplace=True)
    # df
    
    fig = px.pie(df, names='country', values='pop',
                 color='country',
                 title='px pie(names=country, values=pop): asia top 6 + others'              
                 )
    
    fig.show()
    
    # pie chart : Asia top 6 + others + pull(go)
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    pop_min = df['pop'].min()
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002")      
    df.loc[df['pop'] < pop_min, 'country'] = 'Other countries' # Represent only large countries
    df = df.groupby('country').agg(
        {'pop': 'sum', 'year': 'last'}
        )
    df.reset_index(inplace=True)
    
    fig = go.Figure(
        data=[
            go.Pie(
                labels=df['country'], 
                values=df['pop'], 
                pull=[0, 0, 0, 0, 0, 0.3, 0]
                )
        ])
    
    fig.update_layout(title='go pie(labels=country, values=pop, pull=[...])')
    
    fig.show()  
    click image to zoom!
    図5-1
    図5-1では、変数「pop_min」の内容と、PandasのDataFrame(df)の内容を表示してします。 「pop_min」には6位の人口が格納されています。 DataFrameには、上位6位までのデータと「その他」のデータが格納されています。

    click image to zoom!
    図5-2
    図5-2には、DataFrameの内容が円グラフで表示されています。 円グラフには人口の上位6位までの国とその他の国が表示されています。 1位が中国、2位がインド、3位はその他になっています。 ちなみに、日本はその他を含めて7位になっています。

    click image to zoom!
    図5-3
    図5-3では、円グラフから「Other countries(その他)」を分離させています。 円グラフから特定の要素を分離させるには、Plotly Graph Objects(go)の「pull=」を使用します。 図5-1のDataFrameの内容から「Other countries」は先頭から6番目になっています。 なので、引数「pull=」に指定するリスト型データの6番目に「0.3」を設定します。 この数値を調整することで分離させる位置を調整することができます。
  6. Plotly Expressの「pie()」メソッドに引数「hover_data, labels」を追加してホバーテキストをカスタマイズする

    Plotlyは、マウスを円グラフにホバリングさせるとホバーテキストを表示します。 デフォルトでは「names, values」の値が表示されます。 たとえば、円グラフにマウスを移動すると「国名」と「人口」が表示されます。 ここでは、ホバーテキストに「life expectancy(平均寿命)」を追加しています。 ホバーテキストにデータを追加するには「pie()」メソッドの引数に「hover_data=」を追加します。 ホバーテキストにDataFrameのカラム名「lifeExp」ではなく「life expectancy」を 表示させるには「labels=」を追加します。

    # pie chart : add a hovoer_data=, labels=
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    pop_min = df['pop'].min()
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002")      
    df.loc[df['pop'] < pop_min, 'country'] = 'Other countries' 
    df = df.groupby('country').agg(sum)
    df.reset_index(inplace=True)
    
    fig = px.pie(df, names='country', values='pop',
                 hover_data=['lifeExp'], labels=dict(lifeExp='life expectancy'),
                 title='px pie(..., hover_data=, labels=) '              
                 )
    
    fig.show()  
    click image to zoom!
    図6
    図6では、ホバーテキストに「country(国名), pop(人口), life expectancy(平均寿命)」が表示されています。
  7. Plotly Expressの「pie()」メソッドに引数「hover_data」を追加してホバーテキストに人口の「ランク」を表示する

    ここでは、円グラフのホバーテキストに「rank(人口のランク)」を追加しています。 ホバーテキストにデータを追加するには「pie()」メソッドの引数に「hover_data=」を追加します。

    # pie chart : Asia top 8 + hover_data=rank
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(8, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.pie(df, names='country', values='pop',
                 hover_data=['rank'], 
                 title='px pie(...): asia top 8 + hover_data=rank'             
                 )
    
    fig.show()  
    click image to zoom!
    図7
    図7では、ホバーテキストに「country(国名)、pop(人口)、rank(ランク)」が表示されています。
  8. Plotly Expressのpie()メソッドに引数「hole=0.3」を追加してドーナツ型の円グラフにする

    ここでは、ドーナツ型の円グラフを表示します。 円グラフをドーナツ型にするには、「pie()」メソッドの引数に「hole=」を追加します。

    # pie chart : Asia top 8 + hole=0.3
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(8, 'pop')
    
    fig = px.pie(df, names='country', values='pop',
                 color='country',
                 hole=0.3,
                 title='px pie(...): asia top 8 + hole=0.3'              
                 )
    
    fig.show()  
    click image to zoom!
    図8
    図8には、ドーナツ型の円グラフが表示されています。
  9. Figure「update_layput()」メソッドに引数「annotations」を追加してドーナツ型円グラフの中央に「Asia top 8」を表示する

    ここでは、ドーナツ型の円グラフの中央に「Asia top 8」を表示しています。 円グラフに「注釈」を追加するには、 「update_layout()」メソッドに引数「annotations=」を追加します。 annotationsの引数には「text=, x=, y=,...」でテキスト文字、表示位置などを指定します。

    # pie chart : Asia top 8 + hole=0.4 + annotations
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(8, 'pop')
    
    fig = px.pie(df, names='country', values='pop',
                 color='country',
                 hole=0.4,
                 title='px pie(...): asia top 8 + hole=0.1 + annotations=...'             
                )
    
    fig.update_layout(
        # Add annotations in the center of the donut pie.
        annotations=[dict(text='Asia top 8', x=0.50, y=0.5, font_size=20, showarrow=False)]             
    )
    
    fig.show()  
    click image to zoom!
    図9
    図9では、ドーナツ型円グラフの中央に「Asia top 8」が表示されています。
  10. Figureの「update_traces()」メソッドに引数「textinfo」を追加して円グラフに「国名、%」を表示する

    ここでは、円グラフに「国名、人口のパーセント」を表示させています。 円グラフに「国名、%」を追加するには、 「update_traces()」メッソドの引数に「textposition=, textinfo=」を追加します。

    # pie chart : Asia top 6 + textinfo + hover_data
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.pie(df, names='country', values='pop',
                 hover_data=['rank'], 
                 title='px pie(...): asia top 6 + textinfo=...'             
                 )
    
    fig.update_traces(textposition='inside', textinfo='percent+label')
    
    fig.show()  
    click image to zoom!
    図10
    図10では、円グラフに「国名、%」が表示されています。
  11. Figureの「update_traces()」メソッドの引数に「texttemplate」を追加して円グラフに「国名、ランク」を表示する

    ここでは、円グラフに「国名、ランク」を表示させています。 さらに、ホバーテキストには「国名、ランク、人口」を表示させています。 「pie()」メソッドの引数「names=, values=」以外のデータを表示させるには、 「custom_data=」を追加してDataFrameのカラム名「rank」を指定する必要があります。

    ここでは、円グラフの「国名、ランク」を表示させるのに、 「update_traces()」メソッドに引数「textposition=, texttemplate=」を追加しています。 ホバーテキストに「国名、ランク、人口」を表示させるには、 「update_traces()」メソッドに引数「hovertemplate=」を追加します。

    # pie chart : Asia top 6 + custome_data + texttemplate + hovertemplate
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.pie(df, names='country', values='pop',
                 custom_data=['rank'],                                                                  
                 title='px pie(...): asia top 8 + textinfo=...'             
                 )
                                                          
    fig.update_traces(
            textposition='inside', 
            texttemplate="%{label}<br>Rank: %{customdata}",     
            hovertemplate="Country:%{label}<br>Rank: %{customdata}<br>Population: %{value}"
    )
    
    fig.show()  
    click image to zoom!
    図11-1
    図11-1では、円グラフに「国名、ランク」が表示されています。

    click image to zoom!
    図11-2
    図11-2では、ホバーテキストに「国名、ランク、人口」が表示されています。
  12. Plotly Graph Objectsの「Pie()」メソッドに引数「pull」を追加して円グラフから「日本」を切り離して強調する

    ここでは、既に紹介したPlotly Graph Objects(go)の「pull」を使用して円グラフから「日本」を切り離しています。

    # pie chart : Asia top 6 + pull(go)
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    fig = go.Figure(
        data=[
            go.Pie(
                labels=df['country'], 
                values=df['pop'], 
                pull=[0, 0, 0, 0, 0, 0.3]
                )
        ])
    
    fig.update_layout(title='go pie(labels=country, values=pop, pull=[...])')
    
    fig.show()  
    click image to zoom!
    図12
    図12では、円グラフから「日本」が切り離されて強調されています。 DataFrameには日本のデータが先頭から6番目に格納されているので、 「pull=」の値にはリスト型の6番目の要素に「0.3」を指定します。
  13. 全てのコードを掲載

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

    リスト13-1: Article145.py
    # Article145 Plotly Pie Chart 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.pie(
            data_frame=None, 
            names=None, values=None, 
            color=None, 
            facet_row=None, facet_col=None, 
            facet_col_wrap=0, facet_row_spacing=None, facet_col_spacing=None, 
            color_discrete_sequence=None, color_discrete_map=None, 
            hover_name=None, hover_data=None, 
            custom_data=None, 
            category_orders=None, 
            labels=None, 
            title=None, 
            template=None, 
            width=None, height=None, 
            opacity=None, hole=None) 
            → plotly.graph_objects._figure.Figure
    '''
    
    # simple pie chart
    
    country = ['China', 'India', 'Indonesia', 'Japan']
    population = [1280400000, 1034172547, 211060000, 127065841]
    
    fig = px.pie(names=country, values=population)
    # hover(label=China, value=9999999)
    fig.show()
    
    
    # %%
    
    # add a title
    
    fig = px.pie(names=country, values=population,
                 title='px pie(names=country, values=population, title=...)'
                 )
    fig.show()
    
    
    # %%
    
    # add a template (theme)
    
    fig = px.pie(names=country, values=population,
                 template='plotly_dark',  
                 title='px pie(names=, values=, template=plotly_dark)'                
                 )
    fig.show()
    
    
    # %%
    
    # set a defulat templte
    
    pio.templates.default = 'plotly_dark'
    # pio.templates.default = 'plotly_white'
    
    fig = px.pie(names=country, values=population,    
                 title='px pie(...): pio.templates.default=plotly_dark'            
                 )
    fig.show()
    
    
    # %%
    
    # load data from plotly express gapmider()
    raw_df = px.data.gapminder()
    # raw_df.info()
    # raw_df
    # raw_df['continent'].unique()
    df = raw_df.query("continent=='Asia'")
    # df['country'].unique()
    # len(df['country'].unique().tolist())   
    
    
    # %%
    
    fig = px.pie(df,
                 names='country', values='pop',
                 title='px pie(names=country, values=pop, title=...)'
                 )
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 6 + others
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    pop_min = df['pop'].min()
    # pop_min
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002")      
    df.loc[df['pop'] < pop_min, 'country'] = 'Other countries' # Represent only large countries
    df = df.groupby('country').agg(sum)
    df.reset_index(inplace=True)
    # df
    
    fig = px.pie(df, names='country', values='pop',
                 color='country',
                 title='px pie(names=country, values=pop): asia top 6 + others'              
                 )
    
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 6 + others + pull(go)
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    pop_min = df['pop'].min()
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002")      
    df.loc[df['pop'] < pop_min, 'country'] = 'Other countries' # Represent only large countries
    df = df.groupby('country').agg(
        {'pop': 'sum', 'year': 'last'}
        )
    df.reset_index(inplace=True)
    
    fig = go.Figure(
        data=[
            go.Pie(
                labels=df['country'], 
                values=df['pop'], 
                pull=[0, 0, 0, 0, 0, 0.3, 0]
                )
        ])
    
    fig.update_layout(title='go pie(labels=country, values=pop, pull=[...])')
    
    fig.show()
    
    
    # %%
    
    # pie chart : add a hovoer_data=, labels=
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    pop_min = df['pop'].min()
    # pop_min
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002")      
    df.loc[df['pop'] < pop_min, 'country'] = 'Other countries' # Represent only large countries
    df = df.groupby('country').agg(sum)
    df.reset_index(inplace=True)
    # df
    
    fig = px.pie(df, names='country', values='pop',
                 hover_data=['lifeExp'], labels=dict(lifeExp='life expectancy'),
                 title='px pie(..., hover_data=, labels=) '              
                 )
    
    fig.show()
    
    
    # %% 
    
    # pie chart : Asia top 8 + hover_data=rank
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(8, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.pie(df, names='country', values='pop',
                 hover_data=['rank'], 
                 title='px pie(...): asia top 8 + hover_data=rank'             
                 )
    
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 8 + hole=0.3
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(8, 'pop')
    
    fig = px.pie(df, names='country', values='pop',
                 color='country',
                 hole=0.3,
                 title='px pie(...): asia top 8 + hole=0.3'              
                 )
    
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 8 + hole=0.4 + annotations
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(8, 'pop')
    
    fig = px.pie(df, names='country', values='pop',
                 color='country',
                 hole=0.4,
                 title='px pie(...): asia top 8 + hole=0.1 + annotations=...'             
                )
    
    fig.update_layout(
        # Add annotations in the center of the donut pie.
        annotations=[dict(text='Asia top 8', x=0.50, y=0.5, font_size=20, showarrow=False)]             
    )
    
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 6 + textinfo + hover_data
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.pie(df, names='country', values='pop',
                 hover_data=['rank'], 
                 title='px pie(...): asia top 6 + textinfo=...'             
                 )
    
    fig.update_traces(textposition='inside', textinfo='percent+label')
    
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 6 + custome_data + texttemplate + hovertemplate
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    df.reset_index(inplace=True)
    df['rank'] = df.index+1
    
    fig = px.pie(df, names='country', values='pop',
                 custom_data=['rank'],                                                                  
                 title='px pie(...): asia top 8 + textinfo=...'             
                 )
                                                          
    fig.update_traces(
            textposition='inside', 
            texttemplate = "%{label}<br>Rank: %{customdata}",     
            hovertemplate = "Country:%{label}<br>Rank: %{customdata}<br>Population: %{value}"
    )
    
    fig.show()
    
    
    # %%
    
    # pie chart : Asia top 6 + pull(go)
    
    df = raw_df.query("continent=='Asia'") \
            .query("year==2002") \
            .nlargest(6, 'pop')
    
    fig = go.Figure(
        data=[
            go.Pie(
                labels=df['country'], 
                values=df['pop'], 
                pull=[0, 0, 0, 0, 0, 0.3]
                )
        ])
    
    fig.update_layout(title='go pie(labels=country, values=pop, pull=[...])')
    
    fig.show()