カテゴリー

当サイトはアフィリエイトプログラムによる収益を得ています〈景品表示法に基づく表記です)

plt

【plt&pandas】df.plot()でmatplotlibのグラフを作成

2022年3月26日

こんな人にオススメ

pandasのデータフレームからすぐにプロットできるdf.plot()pltのグラフを作成するには?

ということで、今回はpandasdf.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

運営者のメガネです。YouTubeTwitterInstagram、自己紹介はこちら、お問い合わせはこちらから。

運営者メガネ

作成したコード全文

下準備(import

import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px

まずは下準備としてのimportから。pandasを使ってデータフレームを作成、そのままグラフ化するのでpandasだけでいい。

しかし、グラフのレイアウトを変更するにはpltが必要な時もある。一部のレイアウトはpandasだけで対応可能。

また、データフレームはPlotlypxに登録されているものを使用。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の場合は横軸ラベルに加えて縦軸ラベルと凡例もつけてくれる。ただし、それぞれvaluevariableという抽象的な名称。詳しくは以下の記事参照。

【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外では目盛が消える点。

!」をつけるにはforlambda式を使って各目盛(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で可能。引数colormapcolormap='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'で散布図を作成可能。

ただ、以下の注意点がある。

  1. 散布図ではx, yの指定が必要
  2. x, yの指定は列名
  3. インデックスの指定は不可
  4. 複数プロットする場合は1プロット目でaxを定義
  5. 2プロット名以降はaxに追記
  6. プロットの色を指定しないと全てデフォルト色になる

要するに面倒。上のグラフを作成するためのコードを示す。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']でシリーズとして見ると、dtypeobjectdatetime64[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ではxyをそれぞれ指定しなければいけない、かつ、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

さらにさらに、散布図の場合は初めのプロットでaxAxesSubplot)を取得、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'にするだけ。barh(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()で簡単グラフ化

ということで、今回はpandasdf.plot()を使って簡単にpltのグラフを作成する方法について解説した。

pltはPythonで一番メジャーなグラフ作成ライブラリ。そしてpandasもメジャーなデータ扱いライブラリ。

これらの便利なライブラリを活用してこれからも楽してデータの読み込み・グラフ化などを行なってほしい。

関連記事

【plt&subplot】pythonのpltで複数グラフを1つの画像に描く

続きを見る

【plt&棒グラフ】pythonのmatplotlibで棒グラフを作成してみる

続きを見る

【plt&グラフ内グラフ】matplotlibでグラフ内に別グラフやグラフの一部拡大を描画

続きを見る

【plt&mpld3】pltで作ったグラフを後から編集できるようにhtmlで保存

続きを見る

【python&imshow】plt.imshowで2次元配列をマップ化

続きを見る

(9 < x y2)の条件に合った塗りつぶし
【plt&fill_between】matplotlibで領域を塗りつぶし

続きを見る

plt.rcParamsでデフォルトを変更した後のグラフ
【pltテンプレート】matplotlib.pyplotのグラフ作成テンプレート

続きを見る

【plolty&棒グラフ】px.barでバーチャートを作成

続きを見る

【plotly&go.Scatter】plotlyの散布図グラフの描き方

続きを見る

【plotly&px.scatter】pxでの散布図の描き方

続きを見る

ガジェット

2023/9/18

【デスクツアー2022下半期】モノは少なく、でも効率的に Desk Updating #0

今回はガジェットブロガーなのにデスク環境を構築していない執筆者の ...

ライフハック

2023/9/16

【Audible vs YouTube Premium】耳で聴く音声学習コンテンツを比較

ワイヤレスイヤホンが普及し耳で学習することへのハードルが格段に下 ...

完全ワイヤレスイヤホン(TWS)

2023/9/18

【SENNHEISER MOMENTUM True Wireless 3レビュー】全てが整ったイヤホン

今回は高音質・高機能なSENNHEISERのフラグシップ完全ワイヤレスイヤホン「SENNH ...

ライフハック

2023/3/11

【YouTube Premiumとは】メリットしかないから全員入れ

今回はYouTube Premiumを実際に使ってみてどうなのか、どんなメリット/デメリット ...

マウス

2023/8/17

【Logicool MX ERGOレビュー】疲れない作業効率重視トラックボールマウス

こんな人におすすめ トラックボールマウスの王道Logicool MX ERGOが気になるけどऩ ...

ベストバイ

2023/9/18

【ベストバイ2022】今年買って良かったモノのトップ10

2022年ベストバイ この1年を振り返って執筆者は何を買ったのか。ガジェッ& ...

スマホ

2023/1/15

【楽天モバイル×povo2.0の併用】月1,000円の保険付きデュアルSIM運用

こんな人におすすめ 楽天モバイルとpovo2.0のデュアルSIM運用って実際のとこ ...

マウス

2023/9/16

【Logicool MX ERGO vs MX Master 3】ERGOをメインにした決定的な理由

こんな疑問・お悩みを持っている人におすすめ 執筆者はLogicoolのハイエンӠ ...

macOSアプリケーション

2022/9/30

【Chrome拡張機能】便利で効率的に作業できるおすすめの拡張機能を18個紹介する

こんな人におすすめ Chromeの拡張機能を入れたいけど、調べても同じような ...

macOSアプリケーション

2023/5/3

【Automator活用術】Macで生産性を上げる作業の自動化術

今回はMacに標準でインストールされているアプリ「Automator」を使ってできる ...

Pythonを学びたいけど独学できる時間なんてない人へのすゝめ

執筆者は大学の研究室・大学院にて独学でPythonを習得した。

でも社会人になったら独学で行うには時間も体力もなくて大変だ。

時間がない社会人だからこそプロの教えを乞うのが効率的。

ここでは色んなタイプに合ったプログラミングスクールの紹介をする。

  • この記事を書いた人

メガネ

Webエンジニア駆け出し。独学のPythonで天文学系の大学院を修了。常時金欠のガジェット好きでM2 Pro MacBook Pro(30万円) x Galaxy S22 Ultra(17万円)使いの狂人。自己紹介と半生→変わって楽しいの繰り返しレビュー依頼など→お問い合わせ運営者情報、TwitterX@m_ten_pa、 YouTube@megatenpa、 Threads@megatenpa

-plt
-, , ,