[Python] 可視化ライブラリPlotlyのモジュールの使い分け方

Plotly

PlotlyはカナダのPlotly社が開発したインタラクティブなグラフを作成するための可視化ライブラリです。Plotly単独で探索的なデータ分析をすることができますし、同社が開発したwebアプリケーション開発のためのフレームワークであるDashと組み合わせることで高度な可視化を実現するダッシュボードを作成することもできます。
基本から応用まで幅広く活用されるPlotlyですが様々なモジュールがあるために、例えば棒グラフを作成する場合でも実現する方法が複数パターン存在することがあります。今回はPlotly公式HPを基にモジュールの使い分けとそれぞれの基本的な知識をまとめました。Plotlyの基本的な使い方は多くの記事があると思いますので、本記事ではモジュールの使い分けとそれに必要な基本的事項に絞って解説します。

モジュールの選び方

PlotlyにはPlotly Express, Graph Objects, Figure Factoryの3つのモジュールがあります。Plotly Expressが最も簡単かつ少ないコードでグラフが描けるので、Plotly公式HPでは作成できるものはPlotly Expressで作成することが推奨されています。実際には内部でGraph Objectsが動いているのですが、Plotly Expressは高水準のラッパーとなっており、Graph Objectsよりはるかに少ないコーディングでグラフを作成でき、基本的なグラフであれば1つの関数(棒グラフであればpx.bar)を呼び出すだけでグラフが作成できます。ではGraph Objectsはいつ使うのかというと、まだPlotly Expressで実装されていない3次元の特定のグラフ(meshやisosurface)を作成する場合や、様々な種類のグラフが混じったサブプロットや2軸プロットの作成など、細かい設定が必要な場合に使います。最後にfigure_factoryはどうかというと、グラフの中にはFigure Factoryでしか作れないかなり特殊なグラフがあるため、それらのグラフを作成する場合に使います。Figure Factoryで作成できるもので、現在Plotly Expressで作成できるようになったものは”legacy”とされ、非推奨とされています(こちらにFigure Factoryで作成できるグラフとlegacyに該当するグラフの一覧があります)。

Plotly Express

基本的な使い方

作成できるものは最も簡潔にコーディングできるPlotly Expressを使います。慣例的に次のようにモジュールをインポートします。

import plotly.express as ex

棒グラフや折れ線グラフなどの基本的なグラフを1つ作成する場合はPlotly Expressで作成できると考えて問題ありません。グラフの作成手順を示すために、Plotly公式に倣って次のようなシンプルなデータフレームを考えます。(大食い競争のようなコンテストの)参加者毎のフルーツを食べた個数を表したものです。

import pandas as pd

df = pd.DataFrame({
  "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
  "Contestant": ["Alex", "Alex", "Alex", "Jordan", "Jordan", "Jordan"],
  "Number Eaten": [2, 1, 3, 1, 3, 2],
})

例えば棒グラフの場合は次のようにbar関数に最小限の引数を設定するだけでグラフが作成できます。今回は横軸をフルーツの種類、縦軸を各フルーツを参加者が食べた個数とし、参加者毎に色分けした棒グラフを作成しました。

fig = px.bar(df, x="Fruit", y="Number Eaten", color="Contestant", barmode="group")

fig.show()と実行すると下図が表示されます。

Plotly Expressを使うと1行のコードで簡単にグラフを作成することが分かりました。

ファセット

データをカテゴリ毎に分割して複数のグラフを作成する場合はファセットの機能を使います。今回は各フルーツの食べた個数の棒グラフを参加者毎に作成します(AlexとJordanの2つの棒グラフ)。参加者毎のグラフを横に並べる場合はfacet_col引数にカラム名contestantを指定します。尚、縦にグラフを並べる場合はfacet_rowでカラム名を指定し、2つのカテゴリの組み合わせのグラフを格子状に並べる場合は両方の引数を指定します。

fig = px.bar(df, x="Fruit", y="Number Eaten", color="Contestant", facet_col="Contestant")

fig.show()と実行すると下図が表示されます。

これでPlotly Expressの基本的な使い方と複数グラフを作成する方法が分かりました。次章ではGraph Objectsの基本的な使い方と複数グラフを作成する方法を示し、Plotly Expressの作成プロセスと比較します。

Graph Objects

基本的な使い方

ここでは前節で作成したシンプルな棒グラフをGraph Objectsで作成した場合のプロセスを示します。まずは慣例的に次のようにモジュールをインポートします。

import plotly.graph_objects as go

前節で作成した棒グラフと同じものをGraph Objectsで作成するコードは次の通りです。

# 描画領域の作成
fig = go.Figure()

df1 = df[df['Contestant']=='Alex']
df2 = df[df['Contestant']=='Jordan']

# traceの登録
fig.add_trace(go.Bar(x=df1["Fruit"], y=df1["Number Eaten"], name='Alex'))
fig.add_trace(go.Bar(x=df2["Fruit"], y=df2["Number Eaten"], name='Jordan'))

# グラフの調整
fig.update_layout(legend_title_text = "Contestant")
fig.update_xaxes(title_text="Fruit")
fig.update_yaxes(title_text="Number Eaten")

fig.show()を実行すると同じグラフが作成されることが確認できます。

一目コードを見ただけでPlotly Expressよりも長いコードになっていることが分かります。Graph Objectsによるグラフ作成手順をまとめると以下の3つに分けられます。

  1. Figure()で描画領域を作成する
  2. add_traceで描画領域にグラフの実体であるtraceを登録する
  3. update_layoutなどでスタイルなどのグラフの見た目を調整する

Plotly Expressでは内部でGraph Objectsが動いているため、細かな指定をしなくても直感的なグラフが作成できました。しかしGraph Objectsを直接使う場合は、描画領域や参加者毎のグラフの作成、さらに凡例のタイトルなども明示的に指定しなければグラフには反映されません。Plotly公式HPでシンプルなグラフを作成する場合はPlotly Expressの使用が推奨されているのはこのためです。

また見た目はまったく同じグラフが作成されていますが、カーソルをグラフに当てたときに表示される内容はPlotly Expressの方が分かりやすくなっており、その点まで一致させようとするとさらに複雑なコードを書く必要があります(詳細に興味がある方はPlotly公式HPを参照してください)

サブプロット

ではGraph Objectsはどのような場合に使うのでしょうか。前節ではファセットを使ってAlexとJordanが各フルーツを食べた個数に対してそれぞれ棒グラフを作成しました。ここでJordanのグラフだけを折れ線グラフにしたい場合、Plotly Expressでは簡単には作成できません。この場合はGraph Objectsとsubplotsモジュールを合わせて使います。

subplotsモジュールのmake_subplots関数をインポートします。

from plotly.subplots import make_subplots

Jordanのグラフだけを折れ線グラフにする場合は、次のようなコードになります。

# 1×2の描画領域の作成
fig = make_subplots(rows=1, cols=2, subplot_titles=['Contestant=Alex', 'Contestant=Jordan'])

df1 = df[df['Contestant']=='Alex']
df2 = df[df['Contestant']=='Jordan']

# traceの登録
fig.add_trace(go.Bar(x=df1["Fruit"], y=df1["Number Eaten"], name='Alex'), row=1, col=1)
fig.add_trace(go.Scatter(x=df2["Fruit"], y=df2["Number Eaten"], name='Jordan'), row=1, col=2)

# グラフの調整
fig.update_layout(legend_title_text = "Contestant")
fig.update_xaxes(title_text="Fruit")
fig.update_yaxes(title_text="Number Eaten")

make_subplotsで描画領域を作成できるので、Figure()は必要ありません。traceの登録でJordanのグラフを折れ線グラフにするためにScatter関数を使います。fig.show()を実行すると、細かなフォントの違いはありますが、前節のファセットのグラフから棒グラフと折れ線グラフの組み合わせになったことが確認できます。今回の例では折れ線グラフにする必要性はないですが、サブプロットの中で違う種類のグラフを組み合わせるケースは出てきます。Graph Objectsは細かな所までコーディングする必要がある一方で、このように複雑なグラフの作成に柔軟に対応できるのがメリットです。

2軸プロット

水準が異なる数値を比較するために2軸プロットを作成することがありますが、この場合もPlotly Expressで作成することができないのでGraph Objectsを使うことになります。ここではJordanの食べたフルーツの個数を10倍にして、Alexのグラフを棒グラフ、Jordanのグラフを折れ線グラフにして2軸プロットを作成します。この場合もmake_subplots関数を使って次のようにコーディングします。

# 第2のy軸を設定して描画領域を作成
fig = make_subplots(specs=[[{"secondary_y": True}]])

df1 = df[df['Contestant']=='Alex']
df2 = df[df['Contestant']=='Jordan']

# traceの登録、Jordanの食べた個数を10倍に設定
fig.add_trace(go.Bar(x=df1["Fruit"], y=df1["Number Eaten"], name='Alex'), secondary_y=False)
fig.add_trace(go.Scatter(x=df2["Fruit"], y=df2["Number Eaten"]*10, name='Jordan'), secondary_y=True)

# グラフの調整
fig.update_layout(legend_title_text = "Contestant")
fig.update_xaxes(title_text="Fruit")
fig.update_yaxes(title_text="Number Eaten")

make_subplotsのspecs引数で第2のy軸を設定します。traceの登録時にsecondary_y引数にFalseを設定すると左軸を使うグラフ、Trueを設定すると右軸を使うグラフに割り当てられます。ここではAlexのグラフを左軸、Jordanのグラフを右軸に設定しています。fig.show()を実行すると次のような2軸プロットが作成できたことが確認できます。

Figure Factory

限られた特殊なグラフについてはFigure Factoryで作成することになります。それぞれのグラフ毎に関数名や引数が異なるため、Figure Factoryの説明ページを見ながら覚えていくしかありません。ここでは例としてデータフレームのテーブルを表示するTablesの使用例を示します。まずは慣例に従って次のようにインポートします。

import plotly.figure_factory as ff

本記事で使用したデータフレームを使ってTableを作成します。使い方は単純でcreate_table関数にデータフレームを指定します。

fig = ff.create_table(df)

fig.show()で次のようなテーブルが表示されます。

以上が基本的な使用例です。

以前はfigure factoryにのみ実装されていたものの、現在はPlotly Expressでも対応できるようになったグラフはlegacyとされ、figure factoryで作成するのは非推奨となっています。但し、比較的よく使うKDE plotsがDistplotsでのみ作成できたり、ヒートマップを作成する時にいい感じの色合いにするためのcolor_scale設定がAnnotated Heatmapでしか設定できなかったりと、必ずしも使わないということではなさそうです。

まとめ

以上本記事では、Plotlyの各モジュールの使い分けを中心にまとめてきました。PlotlyはMatplotlibやSeabornと並んでよく使われるライブラリですが、機能が多い分どのモジュールを使えばよいか迷う場面が出てきます。そのような時に参考にして頂ければと思います。

Plotlyほど有名ではないですが、細かな設定のしやすさやグラフの見た目が個人的に気に入っているAltairという可視化ライブラリについて次の記事にまとめていますので、ご興味あれば合わせてご覧ください。

PlotlyとDashを組み合わせたダッシュボードの作成事例はこちらの記事にまとめています。

コメント

タイトルとURLをコピーしました