こんな人にオススメ
pnadas
のデータフレームからすぐにプロットするdf.plot()
でplotly
のグラフは作成できるの?
ということで、今回はpandas
のdf.plot()
を使いデータフレームからすぐにplotly
のグラフ作成の方法について解説する。シンプルにdf.plot()
するとmatplotlib
(plt
)でグラフができるが、実は一工夫でplotly
版のグラフも作成可能。
いちいち色んなコードを作成しなくてもサクッとグラフが作成できるのでデータ確認に最適だ。
本記事で解説したグラフ以外の種類のグラフの作成も可能。詳しくはandas
の「pandas.DataFrame.plot」やPlotly
の「Pandas Plotting Backend in Python」を参照。
なお、df.plot()
でplt
のグラフを作成したい場合は以下の記事で開設しているので参照いただきたい。
-
-
【plt&pandas】df.plot()でmatplotlibのグラフを作成
続きを見る
python環境は以下。
- Python 3.10.1
- pandas 1.3.5
- matplotlib 3.5.1
- plotly 5.4.0
- plotly-orca 3.4.2
作成したコード全文
初期のdf.plot()
はplt
import pandas as pd # 初期状態 print(pd.options.plotting.backend) # matplotlib # ['Altair', 'pandas_bokeh', 'Seaborn', 'plotnine', 'IPython vega', 'Plotly', 'Lux', 'Qtpandas', 'D-Tale', 'hvplot', ]
df.plot()
で作成したグラフがどのライブラリのグラフの系列なのかを確認するにはpd.options.plotting.backend
を出力する。
初期状態ではmatplotlilb
、すなわちplt
が設定されている。その他にも色んなライブラリを選択可能だが、今回はその中のplotly
に絞る。ただし、大文字で指定するとエラーになるから注意が必要。
シンプルにすると折れ線グラフ
まずはシンプルにdf.plot()
してみる。この場合は折れ線グラフが描画される。基本デフォルトのグラフだが、フォントサイズは変更している。
グラフのサイズはplt
ではデフォルトの640 x 480ピクセル(4:3)、plotly
ではデフォルトの450 x 700(9:14)ピクセルだ。
以下でグラフ作成の方法を解説するが、まずはこれらのグラフを作成するためのコードを示しておく。
import pandas as pd import plotly.express as px import plotly.io as pio # シンプルにグラフ化 # 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') # df.set_index('date', inplace=True) # これでも可能 print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot() # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_simple" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
使用するデータ
# 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns]
まず使用するデータだけど、これはplotly
のpx
のものを使用。期間初めを1としたアメリカの主要企業の株価データ。
このデータフレームは0列目がdate
列で1列目以降が各企業の株価だけど、そのままだとエラーでグラフ化できない。時刻データと数値データが混在しているから。
なので、df = df.set_index('date')
でdate
列をインデックスに移動している。なお、df.set_index('date')
だけだと元のdf
に反映されないのでdf =
で反映させている。df.set_index('date', inplace=True)
としてもいい。
plotly
のグラフを作成
# pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot() # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_simple" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
plolty
の場合はpd.options.plotting.backend = ‘plotly’
でバックエンドをplotly
に変更する必要がある。これを忘れるとmatplotlib
になってしまう。
グラフ化は単にdf.plot()
でするけど、グラフの表示などを行う際にはfig = df.plot()
として変数に格納しておくと便利。
今回だとグラフのフォントサイズを変更しているが、変数fig
に入れておくことでfig.update_layout
として簡単に変更可能。fig.update_layout
などについては以下の記事参照。
-
-
【plotly&fig作成と更新】add_traceやupdate_layoutの使い方
続きを見る
fig.show()
でグラフ化ができたらあとはグラフを保存するだけ。グラフの保存方法はいくつかあるが、執筆者はorca
を使用している。orca
については以下。
-
-
【plotly&orca】plotlyで静止画保存(orca)
続きを見る
執筆者はいつもhtmlとpng形式でグラフを保存しているから、ここでもこれら2つの拡張子を使用。
凡例や軸ラベルを自動でつけてくれる
実はdf.plot()
でグラフを作成すると自動で凡例や軸ラベルをつけてくれる。後述するように内容を変更することも可能だが、いちいち凡例の設置や軸ラベルの追加などを行う必要がない。
それぞれ指定してしまうと、管理するのも面倒だし変更するのも面倒。自動で追加してくれるのは楽チンでありがたい。
ただし、縦軸ラベルと凡例タイトルは自動でvalue
とvariable
になる。これが嫌ならfig.update_layout
などで別途変更する必要がある。
グラフのサイズやタイトル・軸ラベルを追加
今度はplt
、plotly
それぞれのグラフのレイアウトを変更してみた。変更した内容は以下。
- グラフタイトル
- グラフのテンプレート
- 横軸・縦軸ラベル
- 凡例タイトル
- 縦軸の接尾辞
縦軸の接尾辞は必要ないけど、こういうやり方もあるってことで紹介しておく。まずは上のグラフを作成するための全体コード。
以下でグラフ作成を解説するが、使用するデータやファイル保存名の指定方法は同じなので割愛する。
import pandas as pd import plotly.express as px import plotly.io as pio # グラフレイアウトを変更 # 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # plotlyに変更 pd.options.plotting.backend = 'plotly' # レイアウトの変更は引数で可能 fig = df.plot( # グラフタイトル title='px.data.stock()', # レイアウトのテンプレート template='simple_white', # 横軸、縦軸、凡例のラベル labels=dict( index='date', # 横軸ラベル value='Relative stock price', # 縦軸ラベル variable='Company' # 凡例タイトル ), ) fig.update_yaxes(ticksuffix='!') # y軸に接尾辞をつける # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_layout" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
軸ラベル・凡例タイトルの指定には注意が必要
# plotlyに変更 pd.options.plotting.backend = 'plotly' # レイアウトの変更は引数で可能 fig = df.plot( # グラフタイトル title='px.data.stock()', # レイアウトのテンプレート template='simple_white', # 横軸、縦軸、凡例のラベル labels=dict( index='date', # 横軸ラベル value='Relative stock price', # 縦軸ラベル variable='Company' # 凡例タイトル ), ) fig.update_yaxes(ticksuffix='!') # y軸に接尾辞をつける # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_layout" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
グラフタイトルや軸ラベルを追加・変更したけど、これらはdf.plot()
の中ので引数で設定可能。例えばグラフタイトルはtitle
で可能。
しかし、軸ラベルと凡例タイトルは引数label
の中で行う必要がある。さらに横軸ラベルはindex
、縦軸ラベルはvalue
、凡例タイトルはvariable
。
通常は横軸ならxlabel
やxaxes_title
などで設定するが、ここが異なるので注意が必要。横軸ラベルをfig.update_layout
で変更する場合は以下のようにする。
fig.update_layout(xaxes_title='date')
また、縦軸ラベルに接尾辞をつけたが、これはdf.plot()
では対応できないようだ。なので、これはfig.update_layout
の縦軸版のfig.update_yaxes
で対応。
接尾辞はsuffix
で、軸の目盛に反映させることからticksuffix=’!’
の形式で書く必要がある。
プロットの線の種類を変更
続いてはプロットの線の種類を変更する。普通にグラフ化するだけだと全てのグラフが実線になる。これだと分かりにくい時に使える方法だ。
全体コードは以下。使用するデータはこれまでと同じ。
import pandas as pd import plotly.express as px import plotly.io as pio # プロットの線の種類を変更 # 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot() # 線の種類を変更 fig.data[1].line.dash = 'dash' fig['data'][2]['line']['dash'] = 'dot' fig['data'][3]['line_dash'] = 'dashdot' # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_linestyle" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
線の種類の変更にはいろんな種類がある。ここでは3つの方法で線の種類を変更してみた。それぞれApple、Amazon、Facebook(現Meta)を変更。
fig
の中身はdict
のような構造となっているので、.
を使ってアクセスしてもいいし、[’data’]
のように要素を指定してアクセスしてもいい。
さらにPlotly
では['line']['dash']
のように連続した要素指定は、_
を使って['line_dash']
のように書くことができる。この時の_
をマジックアンダースコアという。
# 線の種類を変更 fig.data[1].line.dash = 'dash' # AAPL fig['data'][2]['line']['dash'] = 'dot' # AMZN fig['data'][3]['line_dash'] = 'dashdot' # FB
これらの方法で線の種類を変更するコードを書いたグラフ化コードが以下。
なお、今回はAAPL、AMZN、FBだけ線の種類を変更したので、それ以外のNFLX、GOOG、MSFTは実線のまま。
# plotly # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot() # 線の種類を変更 fig.data[1].line.dash = 'dash' # AAPL fig['data'][2]['line']['dash'] = 'dot' # AMZN fig['data'][3]['line_dash'] = 'dashdot' # FB # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_linestyle" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
プロットの色を変更
プロットの色を変更するには1プロットずつ指定する必要がある。一括でできないようだ。
import pandas as pd import plotly.express as px import plotly.io as pio # 1プロットずつ色を変更 # 株価のデータ # dateをインデックスに移動するのを1行で済ませた df = px.data.stocks().set_index('date') print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot() # 各ブランドの色 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # 各プロットずつ色を変更 for num, datum in enumerate(fig.data): fig.data[num]['line']['color'] = colors[datum['name']] # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_color" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
プロットの色は各企業のブランドカラーをdict
で作成。GoogleやMicrosoftは複数色あるけど、他のプロットと被らないような色にしておいた。
これらの色を作成したfig
のdata
の中の各企業のプロットカラーに反映させる。fig.data
の中身は以下。
各企業のプロットデータがtuple
形式で入っており、その中にx
やy
などがdict
形式で格納されている。
fig.data
にアクセスできたら、あとは各企業について[’line’][’color’]
というようにプロット線の色を変更すれば良い。
一括で変更できないから、ここではfor
ループで各企業を回すことにする。
# 各ブランドの色 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # 各プロットずつ色を変更 for num, datum in enumerate(fig.data): fig.data[num]['line']['color'] = colors[datum['name']]
あとはグラフ化するのみ。グラフ化部分のコードは以下。
# グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot() # 各ブランドの色 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # 各プロットずつ色を変更 for num, datum in enumerate(fig.data): fig.data[num]['line']['color'] = colors[datum['name']] # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_color" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
df.plot.scatter()
で散布図を作成
散布図を作成するにはdf.plot.scatter
とするだけ。ただし、scatter
の場合はx
とy
の両方を指定する必要があるので注意。
今回はdate
列を横軸に、各企業の株価データを縦軸にする。先ほどまでと同じ。
Plotly
での散布図の作成方法は以下の記事で詳しく解説している。
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
-
-
【plotly&px.scatter】pxでの散布図の描き方
続きを見る
import pandas as pd import plotly.express as px import plotly.io as pio # 散布図を作成 # 株価のデータ df = px.data.stocks().set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' # plotlyは一括でグラフ化可能 fig = df.plot.scatter(x=df.index, y=df.columns[1:].values) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_scatter" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
横軸はデータフレームのインデックスとして指定したdate
を使用するので、df.index
とする。一方で、縦軸はdf.columns[1:].values
とすることで各企業を一括でグラフ化することが可能。
# plotlyは一括でグラフ化可能 fig = df.plot.scatter(x=df.index, y=df.columns[1:].values)
1企業ずつfor
を使ってプロットしてもいいけど、その場合は既存のfig
にfig.add_trace
という形で追加しないといけない。これはこれで面倒。なので一括でプロット。
-
-
【plotly&fig作成と更新】add_traceやupdate_layoutの使い方
続きを見る
[card2 id=""]
あとはフォントサイズ変更とグラフの表示と保存。これまで通り。
# グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' # plotlyは一括でグラフ化可能 fig = df.plot.scatter(x=df.index, y=df.columns[1:].values) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_scatter" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
df.plot.bar()
で棒グラフを作成
棒グラフを作成することも可能。df.plot.bar()
とすることで簡単にグラフ化することができる。ただし、これまでの株価データだと棒グラフにしづらかったので、新たにデータを作成した。
Plotly
での棒グラフの作成方法は以下の記事で詳しく解説している。
-
-
【plotly&棒グラフ】go.Barでバーチャートを作成
続きを見る
-
-
【plolty&棒グラフ】px.barでバーチャートを作成
続きを見る
import pandas as pd import plotly.express as px import plotly.io as pio # 棒グラフを作成 # 株価のデータ df = pd.DataFrame(dict(a=[1, 3, 2], b=[3, 2, 1])) print(df) # a b # 0 1 3 # 1 3 2 # 2 2 1 print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot.bar() # 積み上げ式ではなく、横並びにする場合はbarmode='group' fig.update_layout(barmode='group') # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_bar" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png") # 作成したグラフにHTMLコードを保存 html_code = fig.to_html(include_plotlyjs='cdn', full_html=False) with open(f"{save_name}.txt", mode='w') as f: f.write(html_code)
# 株価のデータ df = pd.DataFrame(dict(a=[1, 3, 2], b=[3, 2, 1])) print(df) # a b # 0 1 3 # 1 3 2 # 2 2 1
plotly
の場合はデフォルトで積み上げ式の棒グラフが作成される。これを横並びにするにはfig.update_layout(barmode='group')
と棒グラフの種類を変更する必要がる。
棒グラフを積み上げ式のままでいいのであれば、barmode
を変更する必要はない。後でグラフ化する。
# pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot.bar() # 積み上げ式ではなく、横並びにする場合はbarmode='group' fig.update_layout(barmode='group')
最終的なグラフ部分のコードは以下。意外とシンプル。
# グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot.bar() # 積み上げ式ではなく、横並びにする場合はbarmode='group' fig.update_layout(barmode='group') # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_bar" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
積み上げ式の棒グラフを作成
積み上げ式の棒グラフの作成は簡単。先ほどの横並びの棒グラフのコードからfig.update_layout(barmode='group')
をコメントアウトするだけ。
Plotly
公式の「Python Figure Reference: layout」のbarmode
の解説ではデフォルトはgroup
だが、なぜかstack
(積み上げ式)がデフォルトとして適用される。
import pandas as pd import plotly.express as px import plotly.io as pio df = pd.DataFrame(dict(a=[1, 3, 2], b=[3, 2, 1])) print(df) # a b # 0 1 3 # 1 3 2 # 2 2 1 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot.bar() # # 積み上げ式ではなく、横並びにする場合はbarmode='group' # fig.update_layout(barmode='group') # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_bar_stack" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
水平の棒グラフ
棒が横向きとなる水平の棒グラフはdf.plot.barh()
で描画可能。h
はhorizontalの略だろう。
基本的にdf.plot.bar()
と同じ考え方でグラフを作成することができる。ここではfig.update_layout(barmode='group')
として横並びの棒グラフを作成した。
import pandas as pd import plotly.express as px import plotly.io as pio # 水平の棒グラフ # 株価のデータ df = pd.DataFrame(dict(a=[1, 3, 2], b=[3, 2, 1])) print(df) # a b # 0 1 3 # 1 3 2 # 2 2 1 print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot.barh() # 積み上げ式ではなく、横並びにする場合はbarmode='group' fig.update_layout(barmode='group') # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_barh" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
facet_row
でサブプロット
最後にサブプロット系の解説を行う。ただし、df.plot()
で作成できるサブプロットは通常のサブプロットとは異なり、facet
というタイプ。
facet
は同じ種類の軸で作成されるサブプロットのグラフのこと。上のグラフの例だと同じ縦軸variable
(ここでは株価)に対してサブプロットしている。
facet
のプロットは主にPlotly
のpx
で使われるプロットの方法。facet
とgo
でのサブプロットについては以下の記事で詳しく解説している。
-
-
【plotly&make_subplots】pythonのplotlyで複数グラフを1つの画像に描く
続きを見る
-
-
【px&facet】plotly.expressでsubplotsを描く
続きを見る
import pandas as pd import plotly.express as px import plotly.io as pio # subplot(facet)を作成 # 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' # facet_rowでサブプロットにしたい変数を選択 fig = df.plot(facet_row='variable') # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # グラフの高さを変更 fig.update_layout(height=1200) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet_row" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
縦軸ラベルを変更
facet_row
でサブプロットっぽいグラフを作成できたが、縦軸がvariable
でわかりづらい。ということで、ここでは縦軸のラベルを変更する。
fig.update_layout
でyaxis_title
とすることで縦軸ラベルを変更することが可能。しかし、サブプロットの場合はそれぞれのグラフがy
, y1
, y2
と名称が異なるのでそれぞれで指定する必要がある。
上のグラフの例ではy
とy2
について縦軸ラベルを変更した。すると一番下のMSFTがy
、その上のNFLXがy2
に対応していることがわかる。y3
以降も同様に指定可能。
データフレームではこれらは一番最後にくるので、データフレームの並びとy
, y2
, ...の並びが逆になることに注意。
import pandas as pd import plotly.express as px import plotly.io as pio # 縦軸ラベルを変更 # 株価のデータ df = px.data.stocks() print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' # facet_rowでサブプロットにしたい変数を選択 fig = df.plot(facet_row='variable') # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # グラフの高さを変更 fig.update_layout(height=1200) #y, y2の縦軸ラベルを変更 fig.update_layout(yaxis_title='y', yaxis2_title='y2') # fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet_row_yaxistitle" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
facet
で軸の共有を解除
先ほどのfacet
のグラフでは、全てのグラフの横軸が共通だった。レイアウトのxaxis
に対してshowticklabels=True
とすることで、共通の軸を解除することができる。
しかし、facet
のグラフの場合は複数のグラフを作っているので、それぞれの軸(xaxis
、xaxis2
、...)でshowticklabels=True
とする必要がある。
for
で1軸ずつ変更することももちろん可能だが、fig.for_each_xaxis
とlambda
式を使うことで1行で処理を書くことが可能。
# 各グラフの横軸ラベルを表示 fig.for_each_xaxis(lambda x: x.update(showticklabels=True))
lambda
式のx
がfor x
のx
に相当するイメージ。各xaxis
をxaxis.update(showticklabels=True))
のように変更している。
この1行を追加するだけで上のグラフのように共通の軸を削除し、各グラフに横軸を追加することが可能になる。
import pandas as pd import plotly.express as px import plotly.io as pio # subplotで軸を共有を解除 # 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # グラフ化 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' fig = df.plot(facet_row='variable') # 各グラフの横軸ラベルを表示 fig.for_each_xaxis(lambda x: x.update(showticklabels=True)) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # グラフの高さを変更 fig.update_layout(height=1200) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet_row_showticklabels" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
facet_col_wrap
でサブプロットの列数を変更
最後にサブプロットの配置を変更する方法を解説する。列数の変更は’facet_col’
, ‘facet_col_wrap’
で行う。先ほどはfacet_row
で行について指定したが、今度はcol
で列指定。
-
-
【px&facet】plotly.expressでsubplotsを描く
続きを見る
facet_col_wrap
は列の数を指定する引数で、上のグラフだとfacet_col_wrap=2
で2列としている。なお、facet_col_wrap
はfacet_row
と併用すると無効化される。後述。
facet_col
にはfacet_row
と同様、facet_col='variable'
としてvariable
を指定するだけ。
import pandas as pd import plotly.express as px import plotly.io as pio # サブプロットのグラフの配置を変更 # 株価のデータ df = px.data.stocks() # 横軸が日付になるようにインデックスを設定 # データの型が異なるのでplotlyのプロット時にエラー # ValueError: Plotly Express cannot process wide-form data with columns of different type. df = df.set_index('date') print(df) # GOOG AAPL AMZN FB NFLX MSFT # date # 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # ... ... ... ... ... ... ... # 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 6 columns] print(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -') # facet_col_wrapでfacetの列数を変更 # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' # なぜかfacet_col_wrapが効かない fig = df.plot(facet_col='variable', facet_col_wrap=2) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet_col_wrap" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
facet_row
とfacet_col_wrap
の併用はdomain
で解決
fig = df.plot(facet_col='variable', facet_col_wrap=2)
とすることでサブプロットの列数を変更できた。
ここでfacet_col
の代わりにfacet_row
を使ってみる。んだが、実はfacet_row
とfacet_col_wrap
の併用はできない。facet_col_wrap
の列数指定が無効になる。
ということで、x
軸・y
軸の引数domain
を使って、各企業のグラフの位置を(x, y)
の相対位置で指定する。位置関係については以下の画像参照。
GOOGに該当するaxis
が右下に来るようにdoamin
のx
, y
の値を調節する必要がある。
なお、x
の最大値を1
としてしまうとグラフ右側のfacet
の凡例と被ってしまう。したがって、ここではx
の最大値は0.95
に調節している。
import pandas as pd import plotly.express as px import plotly.io as pio # pandasで作成するプロットの種類をplotlyに変更 pd.options.plotting.backend = 'plotly' # なぜかfacet_col_wrapが効かない fig = df.plot(facet_row='variable', facet_col_wrap=2) # 右上がx1, y1で左上がx2, y2 fig.update_layout( xaxis_domain=(0.5, 1), # MSFT xaxis2_domain=(0, 0.45), # NFLX xaxis3_domain=(0.5, 0.95), # FB xaxis4_domain=(0, 0.45), # AMZN xaxis5_domain=(0.5, 0.95), # AAPL xaxis6_domain=(0, 0.45), # GOOG yaxis_domain=(0, 0.3), # MSFT yaxis2_domain=(0, 0.3), # NFLX yaxis3_domain=(0.33, 0.63), # FB yaxis4_domain=(0.33, 0.63), # AMZN yaxis5_domain=(0.66, 1), # AAPL yaxis6_domain=(0.66, 1), # GOOG ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # グラフの高さを変更 fig.update_layout(height=1200) fig.show() # グラフ保存 prefix = 'dfplot-plotly' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet_row_domain" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html") pio.write_image(fig, f"{save_name}.png")
pandas
から即グラフ化
ということで、今回はpandas
からすぐにグラフを作成できるdf.plot()
とpd.options.plotting.backend = 'plotly’
でPlotly
形式でグラフ化する方法について解説した。
Plotly
はmatplotlib
とは異なる書き方が必要となるため、とっつきにくいと感じる人も多いだろう。しかし、本記事のdf.plot()
ですぐにプロットできるとまた印象が変わるに違いない。
matplotlib
は飽きた、もっと高機能なグラフを作成したいと思う人への一助となれば幸いだ。
関連記事
-
-
【plt&pandas】df.plot()でmatplotlibのグラフを作成
続きを見る
-
-
【plotly&Scattergl】大量のデータをplotlyで軽くグラフ化
続きを見る
-
-
【px&facet】plotly.expressでsubplotsを描く
続きを見る
-
-
【plotly&px.scatter】pxでの散布図の描き方
続きを見る
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
-
-
【plotly&pattern】棒グラフとかのパターンまとめ
続きを見る
-
-
【plt&棒グラフ】pythonのmatplotlibで棒グラフを作成してみる
続きを見る
-
-
【plolty&棒グラフ】px.barでバーチャートを作成
続きを見る
-
-
【collections.Counter】配列の要素を要素名と個数で勝手に集計
続きを見る