こんな人にオススメ
plotly
の中にpx
ってのがあるけど、これで散布図(scatter)を描くにはどうしたらいい?
ということで、今回はplotly
のplotly.express
、px
で散布図を作成する方法を解説する。plotly
のgo
での散布図については以下参照。
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
px
とgo
の違いはカスタム性と即席性。px
の方が簡単にカスタムすることは難しいけど、サクッとそれなりのグラフを作成可能。一方でgo
だとガッツリ好みのグラフが作成しやすい。
なお、基本的はplotly
公式の「Scatter Plots in Python」に描かれているプロットに沿って、適宜解説を加えたり追加コードを入れたりすることにする。
python環境は以下。
- Python 3.10.1
- numpy 1.21.4
- pandas 1.3.5
- plotly 5.4.0
- plotly-orca 3.4.2
作成したコード全文
下準備(import
)
import numpy as np import pandas as pd import plotly.express as px import plotly.io as pio
まずは下準備としてのimport
関連。メインはpx
と保存用のpio
だが、データの都合上、一部でnumpy
やpandas
を使用するのでimport
。
1種類のデータプロット
まずは簡単な1種類のデータをプロットする方法。プロットする方法には大きく分けると2つある。
x
,y
の配列を直接指定pandas
のデータフレームからx
,y
を指定
基本は2番のデータフレームでプロットすることが多い。シンプルに1種類プロットだけなら配列でもいいけど、複数になったりするとデータフレームの方が楽。
また、データフレームからプロットする方が引数の持つ意味がわかりやすい。
x
, y
の値を指定してプロット
まずはシンプルに、値を指定してプロットする方法。これに関しては普通。シンプルにx
とy
の値に配列を入れて実行するだけ。
注意点はgo
の場合はgo.Scatter
とS
が大文字だったが、px
の場合はpx.scatter
と小文字になるという点。ややこしい。
以下では、px.scatter
でプロットするだけではなく、fig.update_layout
でfig
作成後にフォントサイズを変更している。fig.update_layout
に関しては以下。
-
-
【plotly&fig作成と更新】add_traceやupdate_layoutの使い方
続きを見る
import plotly.express as px import plotly.io as pio # x, yを指定してプロット fig = px.scatter( x=[0, 1, 2, 3, 4], # 横軸の値 y=[0, 1, 4, 9, 16], # 縦軸の値 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # グラフの表示 fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_xy" 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")
データフレームからプロット
データフレームからプロットする場合は、x
, y
などのデータをデータフレームのヘッダ名で指定する。作成したデータフレームは以下。
dict
のkey
で横軸、縦軸となる配列としてx
, y
を指定し、これをpandas
のデータフレームに変換した。
import pandas as pd import plotly.express as px import plotly.io as pio df = pd.DataFrame({'x': [0, 1, 2, 3, 4], 'y': [0, 1, 4, 9, 16]}) print(df) # x y # 0 0 0 # 1 1 1 # 2 2 4 # 3 3 9 # 4 4 16
このデータフレームのx
列、y
列をそれぞれプロットの横軸と縦軸に指定することでプロットすることができる。
データフレームからプロットする場合はpx.scatter
の引数data_frame
を使用する。この引数にデータフレームを入れることで、その他の引数でデータフレームの列名を指定するだけで色んな操作が可能になる。
例えば以下の例だと横軸の値は引数x
だが、これをdf
のx
列にしたいからx=’x’
とするだけで良くなる。いちいちx=df[’x’]
と書かなくてもいい。
# データフレームのヘッダ名からx, yを指定してプロット fig = px.scatter( data_frame=df, # 使用するデータフレーム x='x', # 横軸の値に設定するデータフレームの列名 y='y', # 縦軸に設定するデータフレームの列名 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # グラフの表示 fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_df" 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データのプロットを解説した。ただ、多くの場合は複数データのプロットを行うだろう。ということで、ここでは複数データのプロット方法を解説する。
2次元配列で指定するとエラー
import plotly.express as px import plotly.io as pio # 複数プロットを2次元配列で指定するのはエラー fig = px.scatter( x=[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]], y=[[0, 1, 4, 9, 16], [10, 12, 14, 19, 16]], ) # ValueError: Cannot accept list of column references or list of columns for both `x` and `y`.
まずはシンプルに2次元配列で指定するという方法。これはエラーとなる。データは1次元である必要がある。
1データプロットした後のプロットを追加
続いては1データ追加した後にもう1データを追加するという方法。px.scatter
で配列からプロットできるのは1データだけ。
なので、初めのプロットに追加していく形でどんどんプロットする。追加する際にはadd_trace
やadd_scatter
を使用。詳細は以下の記事参照。
-
-
【plotly&fig作成と更新】add_traceやupdate_layoutの使い方
続きを見る
import plotly.express as px import plotly.io as pio # 既存のfigにプロットを追記 # 1プロット目 fig = px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16],) # 2プロット目(追加分) fig.add_scatter(x=[0, 1, 2, 3, 4], y=[10, 12, 14, 19, 16]) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_add_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")
引数mode
でプロットの種類を変更
ただし、シンプルに追記しただけだと追加分のプロットの種類が点+線となる。したがって、点をプロットしたいなr追記分は明示的に点で描くように指定する必要がある。
プロットの描き方は引数mode
で指定可能。多分、add_trace
はgo
での書き方に準拠している。なので、引数とかが異なるので注意。go
を使った散布図の作成方法は以下。
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
また、追記分のみ凡例が付くのにも注意が必要。これはpx.scatter
の方だとプロットに名前がつかないから。go.Scatter
だとデフォルトでtrace0
やtrace1
のように名前がつく。
plotly
では名前がつくプロットにのみ凡例がつくから、結果として追記分(go
で書いたプロット)だけ凡例が表示されることとなる。
ここではfig.update_traces
で2プロットに対して凡例を表示するようにする引数showlegend=True
として凡例を表示するようにした。そうするとpx.scatter
で作成した青のプロットでは凡例に名前がないことがわかる。
import plotly.express as px import plotly.io as pio # modeを指定するとプロット形式を変更可能 fig = px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16],) fig.add_scatter( x=[0, 1, 2, 3, 4], y=[10, 12, 14, 19, 16], mode='markers' # マーカーだけにする ) # 凡例を表示 fig.update_traces(showlegend=True) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_add_scatter_markers" 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")
これらの解決策は、データフレームを使用すること。データフレームを作成しないといけない場合だと作成するのが面倒だが、あると後々便利。
データフレームで分ければ簡単
データフレームを作成し、プロット時にどの列をどのデータとするかを指定するだけでプロットできる。
ここではx
, y
に加え、2種類のデータを区別するために列name
を追加した。こちらでdata0
とdata1
を指定し、データを区別する。
px.scatter
でdf
, x
, y
でプロットを作成、さらにcolor=’name’
とすることで、色分けをしてくれる。色分けするタイミングで凡例に色とプロット名が反映される。
import pandas as pd import plotly.express as px import plotly.io as pio # データフレームがあれば列名を指定するだけ df = pd.DataFrame( { 'x': [0, 1, 2, 3, 4] + [0, 1, 2, 3, 4], 'y': [0, 1, 4, 9, 16] + [10, 12, 14, 19, 16], 'name': ['data0'] * 5 + ['data1'] * 5, } ) print(df) # x y name # 0 0 0 data0 # 1 1 1 data0 # 2 2 4 data0 # 3 3 9 data0 # 4 4 16 data0 # 5 0 10 data1 # 6 1 12 data1 # 7 2 14 data1 # 8 3 19 data1 # 9 4 16 data1 fig = px.scatter( df, x='x', y='y', color='name' # 色を区別する列名 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_df_2plots" 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")
データをシンボルや色で区別する
ここまではとりあえずプロットしてきた。ここからは色分けやマーカーのシンボル(形状)を異なるものにしてプロット同士が異なるものだということを強調する方法を説明する。
使用するデータはpx
のプリセットデータフレームの「px.data.iris()
」。どうやらあやめのデータのようだ。
使用するデータ
import plotly.express as px import plotly.io as pio # あやめに関するデータ df = px.data.iris() print(df) # sepal_length sepal_width ... species species_id # 0 5.1 3.5 ... setosa 1 # 1 4.9 3.0 ... setosa 1 # 2 4.7 3.2 ... setosa 1 # 3 4.6 3.1 ... setosa 1 # 4 5.0 3.6 ... setosa 1 # .. ... ... ... ... ... # 145 6.7 3.0 ... virginica 3 # 146 6.3 2.5 ... virginica 3 # 147 6.5 3.0 ... virginica 3 # 148 6.2 3.4 ... virginica 3 # 149 5.9 3.0 ... virginica 3 # [150 rows x 6 columns] # ヘッダ名の取得 print(df.columns.values) # ['sepal_length' 'sepal_width' 'petal_length' 'petal_width' 'species' # 'species_id'] # 種類のデータ print(df['species'].unique()) # ['setosa' 'versicolor' 'virginica']
使用するのはplotly
の説明でよく出てくるあやめのデータ。pandas
をimport
していなくても使用できる。
ただ、得られるデータはpandas
のデータフレームで使い勝手もpandas
のデータフレームと同じ。
ヘッダ名の指定で色分けが可能
すでに上で色分けについては解説したが、色分けは分けたいデータの入っている列名を指定するだけ。今回はspecies
列を指定した。これだけで勝手に色分けしてくれる。
また、マーカーのサイズも引数size
に列名を指定することで可能。ここではpetal_length
をマーカーサイズに指定した。
さらに、マウスオーバー時の情報hover_data
も設定。こちらはlist
などで囲った列名(複数可)もしくはデータレームを設定。ここではデータフレーム自体にした。
import plotly.express as px import plotly.io as pio df = px.data.iris() print(df['species']) # 0 setosa # 1 setosa # 2 setosa # 3 setosa # 4 setosa # ... # 145 virginica # 146 virginica # 147 virginica # 148 virginica # 149 virginica # Name: species, Length: 150, dtype: object print(df['petal_length']) # 0 1.4 # 1 1.4 # 2 1.3 # 3 1.5 # 4 1.4 # ... # 145 5.2 # 146 5.0 # 147 5.2 # 148 5.4 # 149 5.1 # Name: petal_length, Length: 150, dtype: float64 fig = px.scatter( df, x='sepal_width', y='sepal_length', color='species', # species列の名称で色分け size='petal_length', # マーカーのサイズをpetal_lengthで決める # hover_data=['petal_width'], # 列名指定するときはlistかtupleで指定 hover_data=df, # データフレームを選択すると全ヘッダ情報が表示される ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_color_str" 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")
色分けを値にするとカラーバーに
先程は文字列であるspecies
列を指定して色分けを行なった。今度は値が入っているpetal_length
列で色分けをする。
petal_length
列には値が入っているんだけど、この列を指定すると勝手にカラーバーが表示されてプロットされる。これは便利。
import plotly.express as px import plotly.io as pio # 数値で色分けすると自動でカラーバーがつく df = px.data.iris() fig = px.scatter( df, x='sepal_width', y='sepal_length', color='petal_length', # 数値で色分けすると自動でカラーバーで示してくれる size='petal_length', # マーカーサイズも同じ列名で可能 hover_data=df, # データフレームを選択すると全ヘッダ情報が表示される ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_color_value" 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")
color_continuous_scale
でカラースケールの変更
また、カラーバーのカラースケールの色を変えたい場合は、引数color_continuous_scale
にカラースケール名を設定すればいい。
カラースケール名はplotly
公式の「Built-in Continuous Color Scales in Python」に例がある。今回はJet
を指定した。これだと青から赤で値の強弱が強調されてわかりやすい。
import plotly.express as px import plotly.io as pio # カラースケールの変更はcolor_continuous_scale df = px.data.iris() fig = px.scatter( df, x='sepal_width', y='sepal_length', color='petal_length', # 数値で色分けすると自動でカラーバーで示してくれる size='petal_length', # マーカーサイズも同じ列名で可能 hover_data=df, # データフレームを選択すると全ヘッダ情報が表示される color_continuous_scale='Jet' # ここにカラースケールの名称を入れる ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_color_value_Jet" 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.iris() print(df['species']) # 0 setosa # 1 setosa # 2 setosa # 3 setosa # 4 setosa # ... # 145 virginica # 146 virginica # 147 virginica # 148 virginica # 149 virginica # Name: species, Length: 150, dtype: object # fig = px.scatter( # df, x='sepal_width', y='sepal_length', # size='species', # サイズに文字の列を指定 # ) # # TypeError: unsupported operand type(s) for /: 'str' and 'int'
マーカー(シンボル)の形状を列名で指定
マーカーの形状も列名で指定することが可能。この場合は引数symbol
を使用する。引数で指定すると勝手に円形や四角で割り当ててくれる。
import plotly.express as px import plotly.io as pio # マーカーの形状を変更 df = px.data.iris() fig = px.scatter( df, x='sepal_width', y='sepal_length', size='petal_length', symbol='species', # speciesでマーカーの形状を指定&凡例も自動作成 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_symbol" 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")
マーカーとカラーバーの両立
しかし、マーカーの形状だけを指定しても(ここではサイズも指定しているけど)同じ色なのでわかりにくい。ということで、color
で数値のデータpetal_length
を入れてみる。
んだけど、この場合だと凡例とカラーバーがダブってしまう。これはこれでダルい。一応、プロットの表示・非表示は凡例の隙間から押せるけど調整が必要。
import plotly.express as px import plotly.io as pio # 凡例とカラーバーの両立だと位置がダブる df = px.data.iris() fig = px.scatter( df, x='sepal_width', y='sepal_length', size='petal_length', # サイズ color='petal_length', # 色 symbol='species', # 形状 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_symbol_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")
凡例の位置基準を変更
アプローチの仕方はいくつもあるけど、 ここでは凡例の位置を移動させることにする。凡例はレイアウトの項目なので、fig.update_layout
を使う。
legend=dict(x=1, xanchor='right')
とすることで、凡例の位置をx=1
としつつ横の位置の基準を凡例に右側にすることが可能。
なお、ここではdict
の入れ子で作成しているけど、アンダースコア_
を使用しても同じ意味。
legend=dict(x=1, xanchor='right') legend_x=1, legend_xanchor='right'
凡例を移動させて作成したグラフが上のグラフ。凡例とカラーバーが重ならないようになったので見やすい。
import plotly.express as px import plotly.io as pio # 凡例の位置と位置基準を変更 fig = px.scatter( df, x='sepal_width', y='sepal_length', size='petal_length', # サイズ color='petal_length', # 色 symbol='species', # 形状 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # 凡例の横位置を1にして位置基準を右に設定 fig.update_layout(legend=dict(x=1, xanchor='right')) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_symbol_color_legend" 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
で編集する。レイアウトの引数coloraxis
の引数colorbar
の引数len
で長さを設定可能。ここではlen=0.5
とした。
import plotly.express as px import plotly.io as pio # カラーバーの長さを変更 df = px.data.iris() fig = px.scatter( df, x='sepal_width', y='sepal_length', size='petal_length', # サイズ color='petal_length', # 色 symbol='species', # 形状 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) # カラーバーを短くする fig.update_layout(coloraxis=dict(colorbar=dict(len=0.5))) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_symbol_color_barlen" 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")
エラーバーの追加
エラーバーとは簡単にいうとその値にどれだけの誤差があるのかを示すもの。一般的な誤差という表現とはニュアンス・意味が異なるからややこしいけど、とにかく値のブレ幅っていうイメージ。
エラーバーは引数error_x
, error_y
で指定することが可能。とりあえずエラーバーのためのデータの作成。今回は適当にデータを作成。e_x
列が横軸、e_y
列が縦軸のエラーとする。
import plotly.express as px import plotly.io as pio df = px.data.iris() # エラーの値を適当に作成 df['e_x'] = df['sepal_width'] / 100 df['e_y'] = df['sepal_length'] / 100 print(df) # sepal_length sepal_width petal_length ... species_id e_x e_y # 0 5.1 3.5 1.4 ... 1 0.035 0.051 # 1 4.9 3.0 1.4 ... 1 0.030 0.049 # 2 4.7 3.2 1.3 ... 1 0.032 0.047 # 3 4.6 3.1 1.5 ... 1 0.031 0.046 # 4 5.0 3.6 1.4 ... 1 0.036 0.050 # .. ... ... ... ... ... ... ... # 145 6.7 3.0 5.2 ... 3 0.030 0.067 # 146 6.3 2.5 5.0 ... 3 0.025 0.063 # 147 6.5 3.0 5.2 ... 3 0.030 0.065 # 148 6.2 3.4 5.4 ... 3 0.034 0.062 # 149 5.9 3.0 5.1 ... 3 0.030 0.059 # [150 rows x 8 columns]
あとはこのデータフレームを使ってこれまで通りグラフを作成するのみ。エラーバーを追加するとホバー情報に各値の誤差が追記される。
fig = px.scatter( df, x='sepal_width', y='sepal_length', color='species', error_x='e_x', error_y='e_y', # エラーバーの追加 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_error_xy" 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")
周辺分布を試す
周辺分布(Marginal Distribution)ってのはプロットの上と右に、メインのプロットから導出されるヒストグラムとかのこと。subplot
に近いイメージ。
-
-
【px&facet】plotly.expressでsubplotsを描く
続きを見る
px
の場合はmarginal_x
とmarginal_y
でそれぞれ上と右にグラフを追加できる。追加できるグラフは以下。
histgram
rug
violin
box
以下ではhistgram
とrug
、violin
とbox
の組み合わせでグラフを作成。
import plotly.express as px import plotly.io as pio # Marginal Distribution(周辺分布) df = px.data.iris() # marginalで上・右に追加でグラフを描画可能 # x, yそれぞれrug, box, violin, histogramが選択可能 fig = px.scatter( df, x='sepal_length', y='sepal_width', marginal_x='histogram', # x軸に平行にhistogram marginal_y='rug', # y軸に平行にrug ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_marginal_rug_histgram" 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 = px.scatter( df, x='sepal_length', y='sepal_width', marginal_x='violin', # x軸に平行にviolin marginal_y='box', # y軸に平行にbox ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_marginal_violin_box" 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")
str以外で指定するとエラー
なお、marginal_x
やmarginal_y
は上と右にしか置くことができない。なので多くても2種類の周辺分布になる。欲張って配列にして指定するとエラーになる。
import plotly.express as px # str以外でで指定するとエラー df = px.data.iris() # 以下ではlistにしてみた fig = px.scatter( df, x='sepal_length', y='sepal_width', marginal_x='violin', # x軸に平行にグラフ marginal_y=['box', 'histogram'], # y軸に平行にグラフ ) # AttributeError: 'NoneType' object has no attribute 'constructor'
色分けもしてみる
さっきは1つのデータだけでプロットしたけど、色分けを追加することも可能。species
で色分けすると各データごとに周辺分布が作成される。これは便利。
import plotly.express as px import plotly.io as pio # speciesで色分けすると分布がわかりやすい df = px.data.iris() fig = px.scatter( df, x='sepal_length', y='sepal_width', marginal_x='histogram', # x軸に平行にhistogram marginal_y='rug', # y軸に平行にrug color='species' ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_marginal_rug_histgram_species" 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")
数値で色分けするとカラーバーのみ
一方でpetal_lengthで色分けするとカラーバーのみが表示されてあまり変化がない。
import plotly.express as px import plotly.io as pio # petal_lengthで色分けすると色が変わるだけ df = px.data.iris() fig = px.scatter( df, x='sepal_length', y='sepal_width', marginal_x='histogram', # x軸に平行にhistogram marginal_y='rug', # y軸に平行にrug color='petal_length', ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_marginal_rug_histgram_petal_length" 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
でsubplot
的な
facet
はsubplot
みたいなもの。厳密には異なるけど、ざっくりは同じ感じ。以下の記事で解説している。
-
-
【px&facet】plotly.expressでsubplotsを描く
続きを見る
指定方法は簡単で列方向にグラフを増やしたいなら引数facet_col
で列名を指定するだけ。また、facet_col_wrap
で列数を指定することも可能。
ただし、facet_row_wrap
という引数はないので注意。列数を基準に複数グラフを作成する。
今回はfacet_col
とfacet_row
で列と行を指定してグラフを作成した。
import plotly.express as px import plotly.io as pio df = px.data.tips() print(df) # total_bill tip sex smoker day time size # 0 16.99 1.01 Female No Sun Dinner 2 # 1 10.34 1.66 Male No Sun Dinner 3 # 2 21.01 3.50 Male No Sun Dinner 3 # 3 23.68 3.31 Male No Sun Dinner 2 # 4 24.59 3.61 Female No Sun Dinner 4 # .. ... ... ... ... ... ... ... # 239 29.03 5.92 Male No Sat Dinner 3 # 240 27.18 2.00 Female Yes Sat Dinner 2 # 241 22.67 2.00 Male Yes Sat Dinner 2 # 242 17.82 1.75 Male No Sat Dinner 2 # 243 18.78 3.00 Female No Thur Dinner 2 # [244 rows x 7 columns] fig = px.scatter( df, x='total_bill', y='tip', color='smoker', # 色は喫煙か否かで区別 facet_col='sex', # 列は性別で区別 facet_row='time' # 行は時間で区別 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet" 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")
px
で最小二乗法
最後はpx
で最小二乗法を使用して線形フィッティングをする方法を解説。px
だけでフィッティングもできるのはかなり楽。最小二乗法ってのはフィッティングするための手法のようのなもの。
上のグラフだと左上がりっぽい散布図にこんな傾向って直線が引かれている。px
の場合、trendline='ols'
と指定することで直線を引くことが可能。その他にもスムージングや移動平均も可能。
import plotly.express as px import plotly.io as pio df = px.data.tips() print(df) # total_bill tip sex smoker day time size # 0 16.99 1.01 Female No Sun Dinner 2 # 1 10.34 1.66 Male No Sun Dinner 3 # 2 21.01 3.50 Male No Sun Dinner 3 # 3 23.68 3.31 Male No Sun Dinner 2 # 4 24.59 3.61 Female No Sun Dinner 4 # .. ... ... ... ... ... ... ... # 239 29.03 5.92 Male No Sat Dinner 3 # 240 27.18 2.00 Female Yes Sat Dinner 2 # 241 22.67 2.00 Male Yes Sat Dinner 2 # 242 17.82 1.75 Male No Sat Dinner 2 # 243 18.78 3.00 Female No Thur Dinner 2 # [244 rows x 7 columns] fig = px.scatter( df, x='total_bill', y='tip', color='smoker', # 色は喫煙か否かで区別 facet_col='sex', # 列は性別で区別 facet_row='time' # 行は時間で区別 ) # グラフ全体とホバーのフォントサイズ変更 fig.update_layout(font_size=20, hoverlabel_font_size=20) fig.show() # グラフ保存 prefix = 'px-scatter' # 保存ファイル名の接頭辞 save_name = f"{prefix}_facet" 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")
なお、実行時に以下のエラーが出た場合はライブラリstatsmodels
を入れることで解決する。
# 以下のエラーが出たら「conda install -c anaconda statsmodels」で # statsmodelsを入れる(Anacondaの場合) # ModuleNotFoundError: No module named 'statsmodels'
フィット結果を出力
フィットした結果を取り出すにはpx.get_trendline_results
を使用する。ただし、中身はこのままだと見ることができない。
# フィット結果 results = px.get_trendline_results(fig) print(results) # px_fit_results # 0 <statsmodels.regression.linear_model.Regressio...
px.get_trendline_results
で取り出した内容に対し、さらに直線情報の中のフィットした結果を見る必要がある。
summary
と以下に示すようにフィットのざっくりとした内容。いつ取得したのかとかも出てくるから面白い。
params
はその名の通りフィットしたデータの係数を示すもの。係数の次数が小さいものから並ぶ。
fit_results = results.px_fit_results.iloc[0] summary = fit_results.summary() # 係数やR2値などのデータのサマリー params = fit_results.params # fit係数
summary
とparams
の結果は以下。
print(summary) # OLS Regression Results # ============================================================================== # Dep. Variable: y R-squared: 0.457 # Model: OLS Adj. R-squared: 0.454 # Method: Least Squares F-statistic: 203.4 # Date: Thu, 11 Nov 2021 Prob (F-statistic): 6.69e-34 # Time: 20:09:30 Log-Likelihood: -350.54 # No. Observations: 244 AIC: 705.1 # Df Residuals: 242 BIC: 712.1 # Df Model: 1 # Covariance Type: nonrobust # ============================================================================== # coef std err t P>|t| [0.025 0.975] # ------------------------------------------------------------------------------ # const 0.9203 0.160 5.761 0.000 0.606 1.235 # x1 0.1050 0.007 14.260 0.000 0.091 0.120 # ============================================================================== # Omnibus: 20.185 Durbin-Watson: 1.811 # Prob(Omnibus): 0.000 Jarque-Bera (JB): 37.750 # Skew: 0.443 Prob(JB): 6.35e-09 # Kurtosis: 4.711 Cond. No. 53.0 # ============================================================================== # Notes: # [1] Standard Errors assume that the covariance matrix of the errors is correctly specified. print(params) # [0.92026961 0.10502452]
このフィット係数をnumpy
でのフィット係数と比較する。numpyでの直線フィットはnp.polyfit
が便利。x
, y
と次数を指定するだけ。
numpy
のフィット結果と比較する
-
-
【python&フィッティング】polyfitとcurve_fitでfitting
続きを見る
import numpy as np import plotly.express as px import plotly.io as pio # numpyのフィットでフィット結果を確かめる df = px.data.tips() par = np.polyfit(x=df['total_bill'], y=df['tip'], deg=1) fit = np.poly1d(par)(df['total_bill']) # 順番が逆だが合っている print(par) # [0.10502452 0.92026961]
np.polyfit
の場合は字数の大きいものから並ぶので順番が前後するけど値は同じ。なのでpx
でサクッとfitしたい時はこれで十分。
データフレームがあれば即席
今回はplotly
のpx
を使用した散布図の描き方について解説した。go
の時はデータが複数あっても配列に追加していくことで複数プロットが可能だった。
一方でpx
の場合は1プロットに追加するかデータフレームからプロットするかという少々面倒な描き方。データフレームの方がデータがまとまってるしプロットも楽にできるけど、データフレームを知らないと大変。
ということで、px
でプロットするならまずはデータフレームの作成・編集方法から学ぶ方が良いのかとも思う。
-
-
【辞書&pandas】dict{name: , val: {a: [~], b:[~]}}のpandas化
続きを見る
関連記事
-
-
【plolty&棒グラフ】px.barでバーチャートを作成
2022/8/19
こんな人にオススメ plotlyのpxで棒グラ ...
-
-
【plotly&ガントチャート】px.timelineでGantt Chartsを作成
2022/8/19
こんな人にオススメ plotlyでガントチ& ...
-
-
【plotly&fill】px.areaで積み上げ塗りつぶし
2023/1/14
こんな人にオススメ pxで塗りつぶ{ ...
-
-
【plotly&px.scatter】pxでの散布図の描き方
2022/8/19
こんな人にオススメ plotlyの中にpxって ...
-
-
【plotly&scatter_matrix】複数種の軸を持つsubplotをpxで描画
2022/8/19
こんな人にオススメ pxにscatter_matrixってい ...
-
-
【plotly&3D】px.scatter_3dとpx.line_3Dで3Dグラフを作成
2022/8/19
こんな人にオススメ plotlyのpxで3Dグラ} ...
-
-
【px&facet】plotly.expressでsubplotsを描く
2022/8/19
こんな人にオススメ plotly.express、pxでsubplotsを ...
-
-
【px&バブルチャート】plotly.expressで各国の収入と平均寿命の時代変化をアニメーションで
2022/8/19
こんな人にオススメ 今は世界的に ...