Home > 記事 > Python > Plotly > 【Plotly】GraphObjectsを使う

記事

【Plotly】GraphObjectsを使う

前回の記事「【Plotly】データベースからデータを読み込んで可視化する」までPlotlyでPlotlyExpressを用いたグラフを描画してきました。PlotlyExpressを用いると、それぞれの軸のデータを渡して一気にグラフを描くことができるという利点があります。しかしPlotly Expressだと折れ線とマークを同時に表示できないという制約があることがわかりました。

ではどうするのかというと、細かい制御をおこなう場合には、Graph Objectsを用いてFigureWidgetを生成します。PlotlyExpressで生成するときのように描画するグラフのデータをまとめて渡すことはできませんが、描画する一つ一つのグラフごとにトレースすることでPlotlyExpressよりも細かい制御ができるようになっています。

そこで今回はGraph Objectsを用いて折れ線とマークを同時に表示しつつ、データのない部分については欠損として折れ線グラフを描画しないようにするにはどのような形でデータを渡せばよいのかをみてゆきます。

1. 方針

新しい方法を試す際には、一つ一つ動作を確認しながらすすめたほうが、近道になります。今回もPlotlyのサイトにあるサンプルを元にして変更を加え、データベースから読み込んだデータを流し込む前までを作成してゆきます。

Plotlyに流し込むデータのフォーマットがわからないと、データベースからデータを取得後に無駄なデータ加工が発生するので、データの下流であるGraph Objectsを用いたグラフ描画を固めます。

次に描画をおこなうのに最適なデータ構造を決定します。

最後に実際にグラフを描いてみます。データベースからの読み込みは次回とします。

2. サンプルの動作確認と修正

PlotlyのLine Chartの「Connect Data Gaps」のサンプルを修正します。もともとのサンプルは以下のようになっています。
 

import plotly.graph_objects as go

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=x,
    y=[10, 20, None, 15, 10, 5, 15, None, 20, 10, 10, 15, 25, 20, 10],
    name = 'No Gaps', # Style name/legend entry with html tags
    connectgaps=True # override default to connect the gaps
))
fig.add_trace(go.Scatter(
    x=x,
    y=[5, 15, None, 10, 5, 0, 10, None, 15, 5, 5, 10, 20, 15, 5],
    name='Gaps',
))

fig.show()

上記をtest.pyというファイル名で保存してください。保存したら実行します。

py test.py

Plotlyがインストールされていたら以下のようにグラフが表示されます。
GraphObjectを用いたグラフ描画
もしPlotlyのインストールがまだの場合には「【Plotly】データを見える化する」を元にPlotlyをインストールしてください。
縦軸、横軸、グラフのタイトル、凡例を変更し、x軸を日付形式にします。y軸に関しては反転させます。青いグラフに関してもGapを入れるようにします。

# -*- coding: utf-8 -*-

import plotly.graph_objects as go

x = ['2021-05-09', '2021-05-08', '2021-05-07', '2021-05-06', '2021-05-05']

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=x,
    y=[1, 2, None, 2, 2],
    name='サイトA 記事1' # Style name/legend entry with html tags
))
fig.add_trace(go.Scatter(
    x=x,
    y=[2, 1, 2, None, 3],
    name='サイトB 記事2',
))

fig.update_yaxes(autorange='reversed')
fig.update_xaxes(tickformat="%Y-%m-%d")
fig.update_layout(title="検索キーワード",xaxis_title="日付",yaxis_title="順位")
fig.show()

早速実行してみます。
順位データのグラフ描画サンプル1

順位が0.5刻みなのが気になります。また日付は1日になっていますが、Windowを拡大すると日付+時刻刻みになりました。軸の刻みを縦軸は1に横軸は1日刻みに変更します。最後から4行目と最後から3行目を以下のように変更します。

fig.update_yaxes(autorange='reversed',dtick=1)
fig.update_xaxes(tickformat="%Y-%m-%d",dtick='1 Day')

再度実行すると軸の刻みが以下のように固定されました。図を拡大しても横軸は1日刻みになっていました。
順位データのグラフ描画サンプル2

レイアウトは思う通りになったため、データ構造を修正してゆきます。

3. データ構造の修正

順位ごとにループを回してグラフを出力できるようにデータ構造を修正します。

# -*- coding: utf-8 -*-

import plotly.graph_objects as go

plotdatas = {
    "検索キーワード1":{
        "日付":['2021-05-09', '2021-05-08', '2021-05-07', '2021-05-06', '2021-05-05']
        ,"サイト":{
            "サイトA 記事1":[1, 2, None, 2, 2]
            ,"サイトB 記事2":[2, 1, 2, None, 3]
        }
    }
    ,"検索キーワード2":{
        "日付":['2021-05-09', '2021-05-08', '2021-05-07', '2021-05-06', '2021-05-05']
        ,"サイト":{
            "サイトA 記事1":[2, 2, None, 2, 1]
            ,"サイトB 記事2":[1, 1, 2, None, 3]
        }
    }
}

for keyword, datas in plotdatas.items():
    fig = go.Figure()
    for key, data in datas.items():
        if key == "日付":
            xvalues = data
        elif key == "サイト":
            site_dic = data

    for site, rank in site_dic.items():
        fig.add_trace(go.Scatter(
            x=xvalues,
            y=rank,
            name=site
        ))
    fig.update_yaxes(autorange='reversed', dtick=1)
    fig.update_xaxes(tickformat="%Y-%m-%d", dtick='1 Day')
    fig.update_layout(title=keyword, xaxis_title="日付", yaxis_title="順位")
    fig.show()

これで以下のようにグラフが2つ表示されました。
ループによるグラフの描画1ループによるグラフの描画2

4. まとめ

Plotly Expressでは描画が難しいグラフをGraph Ojbectsで描画しました。また複数のグラフやグラフのラインを描画するために必要なデータ構造を考え、ループを回すことでグラフを複数描くことができました。

次回はデータベースにアクセスしてグラフを描画します。Graph Objectsに投入するデータ構造を考えた上でSQLを組み立ててゆきます。

Comment on this article

コメントはまだありません。

Send comments

必須
必須  
※ メールアドレスは公開されません
任意
必須
Loading...  Please enter the letters of the image