plotly入門

Python Plotly入門② - 折れ線グラフ(Line Chart)

前回の『Python Plotly入門① - 概要』ではPlotlyがどんなものかについて解説しましたが、今回からは具体的なグラフの作成方法について解説していきたいと思います。

まずはLine Chart(線グラフ)の基本的な使い方を解説したいと思います。

目盛りの設定などもう少し細かいところは、次回説明する予定です。

公式HPの解説はこちらです。

Plotlyの基本的な使い方

まずは線グラフの基本的な描画方法を解説します。

ここでは、株価をプロットしていきたいと思います。

Plotly Express

Plotly Expressという高レベルのAPIでは、Pandasのデータフレームを使って簡単に線グラフを作成することができます。

あとで解説していますが、より細かい設定をしたい場合はPlotly Expressではなくgraph_objectsを使います。

まず、このような株価を基準化したデータフレームを用意します。

Date	          price	        name
2019-06-03	1.000000	スノーピーク
2019-06-04	0.974063	スノーピーク
2019-06-05	1.005041	スノーピーク
2019-06-06	1.014403	スノーピーク
2019-06-07	1.024492	スノーピーク
...	...	...	...
2021-05-25	0.699716	ANA
2021-05-26	0.720060	ANA
2021-05-27	0.738862	ANA
2021-05-28	0.746579	ANA
2021-05-31	0.745035	ANA

plotly.expressをインポートします。

import plotly.express as px

そして、px.lineというメソッドを呼び出します。

fig = px.line(df_vertical, x='Date', y='price', color='name')
fig.show()

引数は、以下の通りです。

  • データフレーム
  • x:x軸に指定したい列
  • y:y軸に指定したい列
  • color:色分けしたい列

すると上のようなグラフが表示されます。

2019年6月1日を1としていますが、キャンプ用品のスノーピークがコロナ後大きく上昇しており(3倍!?)、トヨタや楽天も上昇しているのがわかりますね。

振るわないのがANAですが、需要がここまで落ちると仕方がないですね。

国内消費もいまいちなので三越も下げています。

以下のようにhover_nameに列を指定することで、カーソルを当てたときに大きく表示する項目を選べます。

fig = px.line(df_vertical, x='Date', y='price', color='name', 
              hover_name='name')
fig.show()

hover_name='price'とすると株価が大きく表示されますし、'Date'を指定すると日付が大きく表示されるので、用途に合わせて選べば良いでしょう。

plotly.graph_objects

では、ここからはPlotly Expressを使わないでグラフを作成したいと思います。

Plotly Expressは高レベルのAPIなので、きめ細かな設定ができず、用途によっては思ったグラフが作成できないということがあります。

そういう場合はplotly.graph_objectsのScatterクラスを使って描画します。

以下のデータセットを使います。

Date	      スノーピーク   楽天	トヨタ	ぐるなび	三越	ANA
2019-06-03	1362.90	    1113	6150.75	570.13	879.04	3563.59
2019-06-04	1327.55	    1118	6175.00	551.35	888.81	3520.69
2019-06-05	1369.77	    1116	6332.09	577.05	908.33	3584.07
2019-06-06	1382.53	    1168	6348.57	584.95	898.57	3610.39
2019-06-07	1396.28	    1173	6388.32	583.96	888.81	3589.92

スノーピークだけを表示するのであれば以下のようにできます。

data = go.Scatter(x=df['Date'],
                  y=df['スノーピーク'])
go.Figure(data)
ポイント

これだけでグラフを描画することができます。

  • go.Scatterを使う
  • 引数は
    x = x軸の値
    y = y軸の値
  • go.Figure(data)で描画。

複数の列を表示したい場合は、データをリストにして渡します

data = []
for col in df.columns:
  if col != 'Date':
    data.append(go.Scatter(x=df['Date'],
              y=df[col],
              name=col))
go.Figure(data).show()

add_trace

上のやり方はデータをリストの形で作成し、最後にgo.Figureの引数として渡してやりましたが、add_traceを使うという方法もあります。

こちらは、まずgo.Figure()でインスタンス化し、そのadd_traceメソッドを呼び出すことでデータを追加していく方法です。

私はどちらかというとadd_traceを使って、グラフをどんどん追加していくというやり方を使う場合が多いです。

fig = go.Figure()
for col in df.columns:
  if col != 'Date':
    fig.add_trace(go.Scatter(x=df['Date'],
              y=df[col],
              name=col))
fig.show()

少し発展的な使い方

ここまではPlotlyの基本的な使い方の説明でした。

ここからは、もう少し発展させていきたいと思います。

様々な設定が可能ですが、基本的には辞書型変数として渡すと考えていただければと思います。

データの設定

色の設定

線の色の設定は“line”という引数に設定します。

lineのcolorプロパティに辞書型変数で設定します。

fig = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['スノーピーク'],
              line=dict(color='#87cefa'),
              name='スノーピーク'))
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['楽天'],
              line=dict(color='#90ee90'),
              name='楽天'))
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['ぐるなび'],
              line=dict(color='#da70d6'),
              name='ぐるなび'))
fig.show()

ここでは、dict(color="#…")としていますが、{'color': "#..."}という表記でも構いません。

私も気分で変えていますが、カッコを使う方だとシングル・クオテーションを忘れてしまうのでご注意ください。

マーカーの設定

例えば、線だけではなくマーカーも付けたいということはよくあると思います。

その場合はmodeで指定します。

modeを"lines"にすると線のみ、"markers"にするとマーカーのみ、"markers+lines"で線とマーカーの両方が表示されます。

ですので、散布図の場合はmode="markers"とすればいけます。

fig = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['スノーピーク'],
              line=dict(color='#87cefa'),
              name='スノーピーク'))
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['楽天'],
              line=dict(color='#90ee90'),
              mode='markers',
              name='楽天'))
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['ぐるなび'],
              line=dict(color='#da70d6'),
              mode='markers+lines',
              name='ぐるなび'))
fig.show()

株価の表示の場合はあまり適切ではないですが、"mode"に"text"や"marker+text"とすると文字情報もグラフ上に表示することができます。

さらにマーカーの色やサイズを変えたい場合は、2種類やり方がありますが、一つはmarkersという引数で指定する方法です。

色を変えたい場合はcolorを、サイズを変えたい場合はsizeを、形を変えたい場合はをsymbol, 透明度を指定したい場合はopacityを指定します。

もう一つはmarker_color、marker_size、marker_symbol、marker_opacityを引数として指定する方法です。

以下はmarkersという引数に辞書型変数で設定する1つ目の方法を使った場合です。

fig = go.Figure()
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['スノーピーク'],
              line=dict(color='#87cefa'),
              name='スノーピーク'))
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['楽天'],
              mode='markers',
              marker=dict(color='#90ee90', size=4),
              name='楽天'))
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['ぐるなび'],
              line=dict(color='#dda0dd'),
              mode='markers+lines',
              marker=dict(color='#da70d6', size=8, opacity=0.8, symbol='star'),
              name='ぐるなび'))
fig.show()

symbolはかなりたくさんの種類がありますので、必要に応じてこちらをご参照ください。

例えばこんな感じです。

"0" | "0" | "circle" | "100" | "100" | "circle-open" | "200" | "200" | "circle-dot" | "300" | "300" | "circle-open-dot" | "1" | "1" | "square" | "101" | "101" | "square-open" | "201" | "201" | "square-dot" | "301" | "301" | "square-open-dot" | "2" | "2" | "diamond" | "102" | "102" | "diamond-open" | "202" | "202" | "diamond-dot" | "302" | "302" | "diamond-open-dot" | "3" | "3" | "cross" | "103" | "103" | "cross-open" | "203" | "203" | "cross-dot" | "303" | "303" | "cross-open-dot" | "4" | "4" | "x" | "104" | …

なお、マーカーの色や形は1系列について1種類というわけではなく、リスト型の変数として渡してやることにより、点ごとにマーカーの色や形を変えることができます。

これについては次のところでやってみたいと思います。

テキストの設定

インタラクティブな可視化で個人的に重要だと思っているのは、点が密集している部分を部分的に拡大できること、カーソルを当てたときにテキストを表示することです。

前者は勝手にできますので、ここでは後者の方の対応をしたいと思います。

カーソルを当てたときに表示する情報はtext引数で設定します。(ちなみに、mode='markers+lines+text'と指定すると、カーソルを当てなくてもテキスト情報が表示されるようになります)

データ点に合わせてテキストとマーカーの色を設定するので、そのための関数を作成しておきます。

# 前日比に応じてテキストを作成する
def create_text(value):
  if value < -0.05:
    return f'{abs(value)*100:0.1f}%の大幅下落! 要因調査!'
  elif value < 0.0:
    return f'{abs(value)*100:0.1f}%の下落'
  elif value > 0.05:
    return f'{abs(value)*100:0.1f}%の大幅上昇! イベント確認!'
  elif value >= 0.0:
    return f'{abs(value)*100:0.1f}%の上昇。悪くない!'

# 前日比に応じてマーカーの色を設定する
def set_marker(value, default_color):
  if value < -0.05:
    return '#ff0000'
  elif value > 0.05:
    return '#4169e1'
  else:
    return default_color

textとcolorsに点ごとのテキスト、色を入れてやります。

fig = go.Figure()

text = df['スノーピーク'].pct_change().fillna(0).apply(create_text)
colors = df['スノーピーク'].pct_change().fillna(0).apply(set_marker, default_color='#87cefa')
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['スノーピーク'],
              mode='markers+lines',
              line=dict(color='#87cefa'),
              marker=dict(color=colors),
              text=text,
              name='スノーピーク'))

text = df['楽天'].pct_change().fillna(0).apply(create_text)
colors = df['楽天'].pct_change().fillna(0).apply(set_marker, default_color='#90ee90')
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['楽天'],
              mode='markers+lines',
              line=dict(color='#90ee90'),
              marker=dict(color=colors),
              text=text,
              name='楽天'))

text = df['ぐるなび'].pct_change().fillna(0).apply(create_text)
colors = df['ぐるなび'].pct_change().fillna(0).apply(set_marker, default_color='#da70d6')
fig.add_trace(go.Scatter(x=df['Date'],
              y=df['ぐるなび'],
              mode='markers+lines',
              marker=dict(color=colors),
              text=text,
              line=dict(color='#da70d6'),
              name='ぐるなび'))
fig.show()

すると、あまりキレイではないですが以下のようになります。

皆さんは用途に合わせて、もう少しキレイな図にしていただければと思います。

領域の塗りつぶし

領域を塗りつぶす処理をしたいと思います。

例えば時系列データで±標準偏差で埋めるといった処理を想定しています。

Matplotlibではfill_betweenですね。

では、plotlyではこのように書きます。

company_names = ['スノーピーク', '楽天', 'ぐるなび']
line_colors = ['#87cefa', '#90ee90', '#da70d6']
fill_line_colors = ['rgba(135, 206, 250, 0)', 
                    'rgba(144, 238, 144, 0)', 
                    'rgba(238, 130, 238, 0)']
fill_colors = ['rgba(135, 206, 250, 0.3)', 
               'rgba(144, 238, 144, 0.3)', 
               'rgba(238, 130, 238, 0.3)']

fig = go.Figure()
for company_name, line_color, fill_color, fill_line_color in \
      zip(company_names, line_colors, fill_colors, fill_line_colors):
  # 元の線
  fig.add_trace(go.Scatter(x=df['Date'],
                y=df[company_name],
                line=dict(color=line_color),
                name=company_name))

  # 上限
  fig.add_trace(go.Scatter(x=df['Date'],
                y=df[company_name] + 0.2,
                line=dict(color=fill_line_color),
                fill=None,
                fillcolor=fill_color,
                showlegend=False,
                name=company_name))
  # 下限
  fig.add_trace(go.Scatter(x=df['Date'],
              y=df[company_name] - 0.2,
              line=dict(color=fill_line_color),
              fill='tonexty',
              fillcolor=fill_color,
              showlegend=False,
              name=company_name))
  
fig.show()

19行目から上限と下限を設定しています。

fillという引数ですが、これに“tonexty”としています

これは“to next y”ということで一つ前の線のy軸の値まで塗りつぶすという意味です。

“tozeroy”というのもあり、これはy=0の線(つまりx軸)との間を塗りつぶすものです。

他にも、xの値の方向に塗りつぶす“tonextx"“tozerox”などもあります。

また、今回、上限下限には線は不要なのでfill_line_colorのopacityはRGBAでゼロに指定しています。

fillcolorは塗りつぶす色で、opacityを0.3に指定しています。

上限下限については凡例が不要なためshowlegendをFalseにしています。

すると以下のようなグラフが出来上がります。

最後に簡単なレイアウト設定だけしておきます。

レイアウトの詳細については別の機会に詳しくご紹介する予定です。

fig.show()の前にfig.update_layoutを呼び出し、レイアウトを設定ます。

fig.update_layout(title='株価の推移',
                  yaxis=dict(title='標準化した株価'))

titleはグラフのタイトルで、yaxisはy軸の設定です。

まとめ

今回は、線グラフの基本的な描き方を解説しました。

他にもまだまだ設定できるプロパティがありますので、それについてはこちらで解説しています。

また、表示する範囲の設定などレイアウトを指定する方法の詳細についても後日解説する予定です。

次はこちらもよく使うScatter Plot(散布図)です。

ではまた!

-plotly入門
-, ,