こんな人にオススメ
pandas
のデータフレームからすぐにプロットできるdf.plot()
でplt
のグラフを作成するには?
ということで、今回はpandas
のdf.plot()
を使いデータフレームからすぐにplt
のグラフを作成する方法について解説する。
以下の記事ではPlotly
のグラフを作成する方法を解説しているので、合わせてみていただきたい。
-
-
【plotly&pandas】df.plot()でPlotlyのグラフを作成
続きを見る
pandas
のデータフレームがあるとすぐにグラフを作成できるので、何かしたの確認がしたい時にとても有効だ。
python環境は以下。
- Python 3.10.1
- pandas 1.3.5
- matplotlib 3.5.1
- plotly 5.4.0
作成したコード全文
下準備(import
)
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px
まずは下準備としてのimport
から。pandas
を使ってデータフレームを作成、そのままグラフ化するのでpandas
だけでいい。
しかし、グラフのレイアウトを変更するにはplt
が必要な時もある。一部のレイアウトはpandas
だけで対応可能。
また、データフレームはPlotly
のpx
に登録されているものを使用。px
については以下でカテゴライズしている。
px
はPlotlyの
中でもサクッとグラフを作成するのに長けた存在。少ないコードで動かせるグラフを作成できるので重宝する。
使用データは株価のデータ
import plotly.express as px # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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]
本記事で使用するデータはpx
の中のpx.data.stocks()
のデータフレーム。
このデータフレームではアメリカのGoogleやAppleなど名だたる企業の株価が2018年1月1日を1
として相対的に書かれている。
なお、date
列を横軸として使用するにはdf.set_index('date')
でインデックスにする必要がある。こうしないと横軸が何番目のデータかというナンバリングになる。後述。
初期のdf.plot()
はplt
import pandas as pd # 初期状態 print(pd.options.plotting.backend) # ['Altair', 'pandas_bokeh', 'Seaborn', 'plotnine', 'IPython vega', 'Plotly', 'Lux', 'Qtpandas', 'D-Tale', 'hvplot', ]
df.plot()
で作成したグラフがどのライブラリのグラフの系列なのかを確認するにはpd.options.plotting.backend
を出力する。
初期状態ではmatplotlilb
、すなわちplt
が設定されている。今回はplt
でのグラフ作成なので、特に設定せずそのままで良い。
一応、本記事のコードでは毎回plt
に設定しているが、その他のbackend
にしない限りは設定しなくてもいい。
シンプルに作成すると折れ線グラフ
まずはシンプルにdf.plot()
をしてみると折れ線グラフが作成される。また、横軸は自動で時刻となり、インデックス名の「date
」が自動でつけられる。
Plotly
の場合は横軸ラベルに加えて縦軸ラベルと凡例もつけてくれる。ただし、それぞれvalue
、variable
という抽象的な名称。詳しくは以下の記事参照。
-
-
【plotly&pandas】df.plot()でPlotlyのグラフを作成
続きを見る
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # シンプルにグラフ化 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 折れ線グラフをプロット df.plot() prefix = 'dfplot-plt' plt.savefig(f"{prefix}_simple") plt.show()
横軸をインデックスにしないとナンバリングが横軸に
データフレームのdate
列をインデックスにしない場合、横軸の値がそれぞれのプロット点が「何番目のデータか」というナンバリングになる。
これだと今回のような株価のデータでは役に立たない。なので、面倒だがいちいちdf.set_index('date')
で横軸をインデックスに指定する方がいいだろう。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # インデックスを設定しないと横軸がナンバリングになる # 株価のデータ # インデックスを作成せず使用 df = px.data.stocks() print(df) # date GOOG AAPL AMZN FB NFLX MSFT # 0 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 1 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 3 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 4 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # .. ... ... ... ... ... ... ... # 100 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 101 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 102 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 103 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 104 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 7 columns] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 折れ線グラフをプロット df.plot() prefix = 'dfplot-plt' plt.savefig(f"{prefix}_index") plt.show()
グラフレイアウトを変更
plt
のデフォルトのグラフサイズは「matplotlib.pyplot.figure」によると6.4インチ x 4.8インチ。比率にすると1.333 : 1。サイズが小さいので凡例がグラフとかぶってしまう。
グラフサイズの変更はdf.plot
の引数figsize
で指定可能。また、df.plot
の引数title
でグラフタイトルも指定可能。一方で、軸ラベルや凡例のラベルなどはplt.xlabel
などでdf.plot()
外での指定が必要。
なお、上のグラフでは縦軸目盛に「!
」をつけているが、これはplt.yticks
で「!
」をつける位置とその文字列を指定することで反映可能。難点はグラフticks
外では目盛が消える点。
「!
」をつけるにはfor
やlambda
式を使って各目盛(tick
)に「!
」を追加したらいい。ここではlambda
式を使って追加した。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # グラフレイアウトを変更 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 折れ線グラフをプロット df.plot( title='px.data.stock()', # グラフタイトル figsize=(16, 9), # グラフサイズ ) # レイアウトを変更 plt.xlabel('date') # 横軸ラベル plt.ylabel('Relative stock price') # 縦軸ラベル plt.legend(title='Company') # 凡例の表示とそのタイトル # 軸目盛を変更(特に意味はない) ticks = (0, 0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2.) # 縦軸の目盛 # y軸に接尾辞をつける label = list(map(lambda x: f"{x}!", ticks)) print(label) # ['0!', '0.2!', '0.4!', '0.6!', '0.8!', '1!', '1.2!', '1.4!', '1.6!', '1.8!', '2.0!'] plt.yticks(ticks=ticks, labels=label) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_layout") plt.show()
style
でプロットの線の種類を変更
これまでのプロットは全て実線で作成して色で企業を分けてきた。しかし、色だけではなく線の種類でもプロットを区別することも可能。
線の種類の指定はdf.plot()
の引数style
で可能。今回はstyle=['-', '--', ':', '-.']
で実線、破線、点線、一点鎖線を指定。
なお、指定されてなかった後半の2企業Netflix(NFLX)とMicrosoft(MSFT)はデフォルトの実線が反映されることになる。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # プロットの線の種類を変更 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # ラインスタイルを変更 # 指定するスタイルの数がデータよりも少ない場合は自動的に実線になる df.plot(style=['-', '--', ':', '-.']) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_linestyle") plt.show()
colormap
でプロットの色を変更
一方でグラフプロットの色を変更することも可能。ここではカラーマップを指定して一括で色を変更する。1プロットずつの変更は次の項目で解説。
カラーマップとは虹色のように、一定の色のセットのこと。虹色だと紫から緑、赤にかけてセットになっている。詳しくはmatplotlib
の「Choosing Colormaps in Matplotlib」に書かれている。
カラーマップの指定はdf.plot()
の引数colormap
で可能。引数colormap
にcolormap='jet'
と指定することでjet
の色の反映が可能となる。
以下のグラフはPastel1
というカラーマップ。薄すぎる。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # プロットの色をcolormapで変更 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # colormapでプロットの色を変更 df.plot(colormap='jet') prefix = 'dfplot-plt' plt.savefig(f"{prefix}_colormap_jet") plt.show() # カラーマップをPastel1に df.plot(colormap='Pastel1') prefix = 'dfplot-plt' plt.savefig(f"{prefix}_colormap_Pastel1") plt.show()
color
で1プロットずつ色を変更
引数color
で色を指定することで1プロットずつ、色を変更することも可能。ここでは各企業のブランドカラーを使用。なお、GoogleとMicrosoftは複数色がブランドカラーなので、他と被らない色をチョイス。
ここでは色の指定はdict
で行なったが、tuple
などでも指定可能。
なお、dict
で指定すると指定の順番がデータフレームの並び順じゃなくてもいい。以下ではデータフレームの順番とは異なるように、GOOGをdict
の途中に入れているが、ちゃんとGOOGで指定したviolet
が反映されている。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # 1プロットずつ色を変更 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 各ブランドの色 # dictではなくtupleなどでも可能 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # colorでプロットの色を変更 df.plot(color=colors) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_colors") plt.show() # 色の指定の順番をデータフレームの順とは異なるように設定 colors = { 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314', 'GOOG': 'violet' # GOOGを最後に持ってきた } # colorでプロットの色を変更 df.plot(color=colors) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_colors_orderqqq") plt.show()
kind='scatter'
で散布図を作成
これまでは折れ線グラフを作成してきた。しかし時には散布図(scatter
)を作成したいと思う時もあるだろう。その時はdf.plot()
の引数kind='scatrter'
で散布図を作成可能。
ただ、以下の注意点がある。
- 散布図では
x
,y
の指定が必要 x
,y
の指定は列名- インデックスの指定は不可
- 複数プロットする場合は1プロット目で
ax
を定義 - 2プロット名以降は
ax
に追記 - プロットの色を指定しないと全てデフォルト色になる
要するに面倒。上のグラフを作成するためのコードを示す。print
部分は省いている。
次からは各項目について解説する。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # 散布図を作成 # 株価のデータ df = px.data.stocks() # scatterは横軸の指定も必要 # 指定は列名で行うので、インデックスを指定するとグラフ化できない # date列を時刻に変更 df['date'] = pd.to_datetime(df['date']) # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 各ブランドの色 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # scatterは横軸と縦軸の指定が必要 # 1つ目のプロットでaxを作成 # 2つ目以降のプロットではこのaxを指定 for num, name in enumerate(df.columns[1:]): # 初めのプロットでaxesを取得 if num == 0: ax = df.plot( kind='scatter', x='date', y=name, label=name, color=colors[name], # プロットの色を指定しないと全て青になる ) else: df.plot( kind='scatter', x='date', y=name, label=name, color=colors[name], ax=ax, # 定義したaxesに追加 ) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_scatter") plt.show()
date列を時刻に変換
# 株価のデータ df = px.data.stocks() # scatterは横軸の指定も必要 # 指定は列名で行うので、インデックスを指定するとグラフ化できない print(df['date']) # 0 2018-01-01 # 1 2018-01-08 # 2 2018-01-15 # 3 2018-01-22 # 4 2018-01-29 # ... # 100 2019-12-02 # 101 2019-12-09 # 102 2019-12-16 # 103 2019-12-23 # 104 2019-12-30 # Name: date, Length: 105, dtype: object # date列を時刻に変更しないと文字列として扱われる df['date'] = pd.to_datetime(df['date']) print(df['date']) # 0 2018-01-01 # 1 2018-01-08 # 2 2018-01-15 # 3 2018-01-22 # 4 2018-01-29 # ... # 100 2019-12-02 # 101 2019-12-09 # 102 2019-12-16 # 103 2019-12-23 # 104 2019-12-30 # Name: date, Length: 105, dtype: datetime64[ns] print(df) # date GOOG AAPL AMZN FB NFLX MSFT # 0 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 1 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 3 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 4 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # .. ... ... ... ... ... ... ... # 100 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 101 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 102 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 103 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 104 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 7 columns]
まずはデータフレームのdate
列を時刻に変換する。変換せずにグラフ化すると横軸が文字列のままになって渋滞する。後ほどグラフ化する。
時刻への変換はpd.to_datetime(df['date'])
で行う。ただ、pd.to_datetime(df['date'])
だけだと変換が上書きされないのでdf['date'] =
でdate
列を時刻に変換して上書きしている。
print(df)
で確認しても変化は見られないが、df['date']
でシリーズとして見ると、dtype
がobject
→datetime64[ns]
となっているのがわかる。時刻となっている。
散布図作成
# バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 各ブランドの色 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # scatterは横軸と縦軸の指定が必要 # 1つ目のプロットでaxを作成 # 2つ目以降のプロットではこのaxを指定 for num, name in enumerate(df.columns[1:]): # 初めのプロットでaxesを取得 if num == 0: ax = df.plot( kind='scatter', x='date', y=name, label=name, color=colors[name], # プロットの色を指定しないと全て青になる ) else: df.plot( kind='scatter', x='date', y=name, label=name, color=colors[name], ax=ax, # 定義したaxesに追加 ) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_scatter") plt.show()
複数プロットで散布図を作成する際には、色を指定する方が良い。指定しない場合は全てのプロットの色がデフォルトの色(通常は青)となる。ここでは先ほどの色の指定の方法でdict
を使用。
また、scatter
ではx
とy
をそれぞれ指定しなければいけない、かつ、df.index
のようにインデックス単位での指定ができない。なのでx='date'
として横軸を決める。
さらに全データを一括でプロットしようとするとエラーとなる。したがって、for
を使って1企業ずつプロットしている。
# 一括でのグラフ化はできない df.plot(kind='scatter', x='date', y=df.columns[1:].values) # ValueError: x and y must be the same size
さらにさらに、散布図の場合は初めのプロットでax
(AxesSubplot
)を取得、2プロット目以降はこのax
に追記する必要がある。
なので、for
の中でif
の分岐を使って1プロット目かそれ以降かを判別。1プロット目ならax
を定義して、2プロット目以降はこのax
に追記している。面倒。
df.plot.scatter
でも可能
プロットの種類をdf.plot(kind='scatter')
で指定したが、実はdf.plot.scatter
でも可能。お好みで使ってほしい。
横軸を時刻にしないと横軸が渋滞する
仮にdf['date'] = pd.to_datetime(df['date'])
で横軸を時刻に変換せずにグラフ化すると上のグラフのように、横軸がえらいことになる。
これは横軸を文字列のまま指定しているから。初期状態だとデータフレームのdate
列はdtype: object
。これが原因。
散布図なので各プロットに対して横軸が設定されているっぽくて、これによって渋滞してしまう。面倒。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # dateを時刻にしないと横軸が渋滞する # 株価のデータ df = px.data.stocks() print(df) # date GOOG AAPL AMZN FB NFLX MSFT # 0 2018-01-01 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # 1 2018-01-08 1.018172 1.011943 1.061881 0.959968 1.053526 1.015988 # 2 2018-01-15 1.032008 1.019771 1.053240 0.970243 1.049860 1.020524 # 3 2018-01-22 1.066783 0.980057 1.140676 1.016858 1.307681 1.066561 # 4 2018-01-29 1.008773 0.917143 1.163374 1.018357 1.273537 1.040708 # .. ... ... ... ... ... ... ... # 100 2019-12-02 1.216280 1.546914 1.425061 1.075997 1.463641 1.720717 # 101 2019-12-09 1.222821 1.572286 1.432660 1.038855 1.421496 1.752239 # 102 2019-12-16 1.224418 1.596800 1.453455 1.104094 1.604362 1.784896 # 103 2019-12-23 1.226504 1.656000 1.521226 1.113728 1.567170 1.802472 # 104 2019-12-30 1.213014 1.678000 1.503360 1.098475 1.540883 1.788185 # [105 rows x 7 columns] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 各ブランドの色 colors = { 'GOOG': '#34a853', 'AAPL': '#000000', 'AMZN': '#ff9900', 'FB': '#1877f2', 'NFLX': '#e50914', 'MSFT': '#f65314' } # scatterは横軸と縦軸の指定が必要 # 1つ目のプロットでaxを作成 # 2つ目以降のプロットではこのaxを指定 for num, name in enumerate(df.columns[1:]): # 初めのプロットでaxesを取得 if num == 0: ax = df.plot( kind='scatter', x='date', y=name, label=name, color=colors[name], # プロットの色を指定しないと全て青になる ) else: df.plot( kind='scatter', x='date', y=name, label=name, color=colors[name], ax=ax, # 定義したaxesに追加 ) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_scatter_date") plt.show()
kind='bar'
で棒グラフを作成
続いては棒グラフの作成。株価のデータのままだと棒グラフにしづらかったので、新たにデータフレームを作成。
グラフ化は簡単で、df.plot(kind='bar')
だけ。Plotlyの場合は初期の棒グラフが積み上げ式だったが、plt
は横並び。
-
-
【plotly&pandas】df.plot()でPlotlyのグラフを作成
続きを見る
import pandas as pd import matplotlib.pyplot as plt # 棒グラフを作成 # データを作成 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 # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 棒グラフを作成 df.plot(kind='bar') prefix = 'dfplot-plt' plt.savefig(f"{prefix}_bar") plt.show()
stacked=True
で積み上げ式の棒グラフ
積み上げ式の棒グラフの作成も簡単にできる。df.plot()
の引数stacked=True
にするだけ。積み上げ式にすると累計の値がわかりやすい。
import pandas as pd import matplotlib.pyplot as plt # 積み上げ式の棒グラフを作成 # データを作成 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 # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' df.plot(kind='bar', stacked=True) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_bar_stacked") plt.show()
kind='barh'
で水平の棒グラフ
水平の棒グラフの作成も簡単にできる。df.plot()
の引数kind='barh'
にするだけ。bar
にh
(horizontal:水平)をつけるだけ。シンプル。
import pandas as pd import matplotlib.pyplot as plt # データを作成 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 # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # 水平の棒グラフを作成 df.plot(kind='barh') prefix = 'dfplot-plt' plt.savefig(f"{prefix}_barh") plt.show()
barh
でもstacked=True
で積み上げ可能
もちろん水平のグラフの場合もstacked=True
で積み上げ式に変更可能。選択肢が広がる。
import pandas as pd import matplotlib.pyplot as plt # 水平の棒グラフ # データを作成 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 # 水平かつ積み上げ式の棒グラフを作成 df.plot(kind='barh', stacked=True) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_barh_stacked") plt.show()
subplots
でサブプロット(複数グラフ)
サブプロットとは1つのグラフ内に複数のグラフを作成するというもの。以下の記事でplt
のサブプロットを解説している。
-
-
【plt&subplot】pythonのpltで複数グラフを1つの画像に描く
続きを見る
指定は簡単でdf.plot()
の引数subplots=True
にするだけ。これだけで1列のサブプロットができ、自動で凡例も分けてくれる。
なお、横軸は自動で共有となるので1つしか表示されない。共有の解除は後述。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # subplotを作成 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # サブプロットのグラフを作成 df.plot(subplots=True) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_subplot") plt.show()
サブプロットのレイアウトを変更
さっきのサブプロットだと、横軸ラベルはつけてくれているが、凡例のタイトルや縦軸ラベルがついていない。
ここではレイアウト変更の一環として縦軸ラベル、横軸ラベル、凡例タイトルを変更した。
なお、変更は各グラフについて行う必要がある。軸については散布図の解説でも使ったax
を使用。このax
の要素ごとに指定する。
# グラフ全体 print(ax) # [<AxesSubplot:xlabel='date'> <AxesSubplot:xlabel='date', ylabel='stock'> # <AxesSubplot:xlabel='date'> <AxesSubplot:xlabel='date'> # <AxesSubplot:xlabel='date'> <AxesSubplot:xlabel='date'>] print(ax[0]) # GOOG # AxesSubplot(0.125,0.77;0.775x0.11)
ここではax[0]
のGOOGに縦軸ラベル、ax[1]
のAAPLに横軸ラベル、ax[2]
のAMZNに凡例タイトルを設定した。それ以外の企業については変更していないのでデフォルトのまま。
しかし、横軸ラベルについてはデフォルトで軸の共有がなされているので軸ラベルの変更は適用されない。次で解説する軸ラベルの共有の解除を行なうと変更可能。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # subplotのレイアウトを変更 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # サブプロットのグラフを作成 # 横軸ラベルがないことを確認すべく、縦長のグラフにする ax = df.plot(subplots=True, figsize=(16, 26),) # axには全てのプロットの情報が入っている # 要素ごとにレイアウトの変更を適用 ax[0].set_ylabel('stock') # 縦軸ラベル ax[1].set_xlabel('dateq2111111111') # 横軸ラベル ax[2].legend(title='Company') # 凡例の表示とそのタイトル prefix = 'dfplot-plt' plt.savefig(f"{prefix}_subplot_label") plt.show()
sharex
, sharey
で軸の共有を解除
df.plot
でサブプロットを作成するとデフォルトでは軸が共有される。しかし、時には軸の共有を解除したい時もあるだろう。
その時は横軸ならsharex=False
、縦軸ならsharey=False
とすることで軸の共有を解除することが可能。共有を解除すると各軸にラベルが追加されるので、先程の軸ラベルの変更が適用できる。
ここでは1列のサブプロットで横軸が共有されているので、sharex=False
で横軸の共有を解除した。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # subplotで共通の軸を削除 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # サブプロットのグラフを作成 df.plot( subplots=True, figsize=(16, 20), # グラフサイズ sharex=False # 横軸の共有を解除 ) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_subplot_sharex") plt.show()
サブロットの配置を変更
最後にサブプロットでの配置を変更する。デフォルトでは1列だが、これだと横長すぎる。上のグラフのように2列にすることで余白を持って見やすくなる。
指定は簡単で、df.plot()
の引数layout=(行数, 列数)
とするだけ。ここではlayout=(3, 2)
で3行2列にした。
デフォルトでは軸共有があるが、これは横軸だけ。縦軸も共有にしたい場合はsharey=True
にする。
ただし、軸の共有なので各グラフの最小値・最大値も共有となる。差が激しいグラフを扱う時には見え方に注意が必要。
import pandas as pd import matplotlib.pyplot as plt import plotly.express as px # subplotの列数を変更 # 株価のデータ df = px.data.stocks() # dateを横軸にするために、date列をインデックスへ移動 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] # バックエンドにmatplotlibを指定 pd.options.plotting.backend = 'matplotlib' # サブプロットのグラフを作成 df.plot( subplots=True, figsize=(16, 9), # グラフサイズ layout=(3, 2) # 3行2列 ) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_subplot_layout") plt.show() # sharey=Trueで縦軸を共有 df.plot( subplots=True, figsize=(16, 9), # グラフサイズ layout=(3, 2), # 3行2列 sharey=True # 縦軸を共有 ) prefix = 'dfplot-plt' plt.savefig(f"{prefix}_subplot_layout_sharey") plt.show()
df.plot()
で簡単グラフ化
ということで、今回はpandas
のdf.plot()
を使って簡単にpltのグラフを作成する方法について解説した。
plt
はPythonで一番メジャーなグラフ作成ライブラリ。そしてpandas
もメジャーなデータ扱いライブラリ。
これらの便利なライブラリを活用してこれからも楽してデータの読み込み・グラフ化などを行なってほしい。
関連記事
-
-
【plt&subplot】pythonのpltで複数グラフを1つの画像に描く
続きを見る
-
-
【plt&棒グラフ】pythonのmatplotlibで棒グラフを作成してみる
続きを見る
-
-
【plt&グラフ内グラフ】matplotlibでグラフ内に別グラフやグラフの一部拡大を描画
続きを見る
-
-
【plt&mpld3】pltで作ったグラフを後から編集できるようにhtmlで保存
続きを見る
-
-
【python&imshow】plt.imshowで2次元配列をマップ化
続きを見る
-
-
【plt&fill_between】matplotlibで領域を塗りつぶし
続きを見る
-
-
【pltテンプレート】matplotlib.pyplotのグラフ作成テンプレート
続きを見る
-
-
【plolty&棒グラフ】px.barでバーチャートを作成
続きを見る
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
-
-
【plotly&px.scatter】pxでの散布図の描き方
続きを見る