matplotlib.datesで時系列データのグラフの軸目盛の設定をする

HourLocator example

matplotlib.datesを使用して横軸に時間をとったグラフを描く際に、
軸目盛(ticks)と目盛ラベル(ticklabels)の設定を行う方法です。

ポイントとコード例

使用するライブラリはmatplotlib.datesです。
https://matplotlib.org/api/dates_api.html

import matplotlib.dates as mdates

という形でimportしておきます。

軸目盛の設定は、LocatorFormatterの2種類に対して行います。
次のコード例では、1分間隔のデータ4ヶ月分の描画に対し、1週間ごとに目盛を設定しています。

# データフレームの準備
start_datetime = datetime.datetime(2017, 11,1)
end_datetime = datetime.datetime(2018, 3,1)
target_df = sample_df[(sample_df["datetime"] > start_datetime)&(sample_df["datetime"] < end_datetime)]

# 描画
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(target_df["datetime"], target_df["C1"])

# 軸目盛の設定
ax.xaxis.set_major_locator(mdates.DayLocator(bymonthday=None, interval=7, tz=None))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))

## 補助目盛りを使いたい場合や時刻まで表示したい場合は以下を調整して使用
# ax.xaxis.set_minor_locator(mdates.HourLocator(byhour=range(0, 24, 1), tz=None))
# ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d\n%H:%M:%S"))

# 軸目盛ラベルの回転
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, fontsize=10);

ax.grid()

描画結果はこちらです。
example1_image

軸ラベルの回転以外は余計な要素を極力省いています。
軸ラベルの回転についてもこちらをご参照ください。
https://bunsekikobako.com/rotate_label_for_graph/

解説

軸目盛関連の設定は下記の2行です。

ax.xaxis.set_major_locator(mdates.DayLocator(bymonthday=None, interval=7, tz=None))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))

ここでは簡単に解説を行います。

mdates.Locatorについて

今回は日ごとに目盛を設定するため、LocatorにはDayLocatorを使用しています。

よく使うLocatorとしては今回使用したDayLocator(日単位)、HourLocator(時間単位)、MinuteLocator(分単位)などがあります。

少し変わったものとしては曜日の情報を渡すWeekdayLocatorがあります。

それぞれのLocatorには固有の引数と共通の引数があります。

固有の引数

固有の引数は、bymonthdayやbyhourなどのby~です。
使う際は、初めに挙げた3つのLocatorではリストやrangeなどのiterableなオブジェクトを渡します。

例えば、mdates.HourLocatorにbyhour=range(0, 24, 4)を渡すと、
0時から4時間ごとに目盛を設定してくれます。

WeekdayLocatorだけは異なり、byweekdayにはmdates.MOなどを渡します。
これは月曜日を示すオブジェクトですね。MO, TU, WE, TH, FR, SA, SUで
月曜日~日曜日を表します。
ドキュメントのかなり上の方で出てくるので、そちらもご参照ください。

共通の引数

共通の引数にはintervalとtzがあります。
intervalは渡した値ごとに目盛を設定してくれます。
tzはtimezone情報です。

なお、by~とintervalは同時に使用できないようのでご注意ください。

mdates.Formatterについて

Formatterには今回使用したDateFormatter以外にはAutoDateFormatterやIndexFormatterなどがあります。

今回のような用途では基本的にはDateFormatterを使用すれば問題ないと思います。

フォーマットの書き方についてはdatetime.strftime()を参考にすればよいようです。
https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior

まとめ

LocatorとFormatterにはいくつかレパートリーがありますが、
基本的な使い方を理解すれば、かなり自由に設定できるようになるかと思います。

matplotlib.datesのドキュメントへのリンク(再掲)
https://matplotlib.org/api/dates_api.html

応用例

応用して作成したグラフのコードを2つ紹介します。

引数にbyhourを使用する+補助目盛線を設定する例

まずは応用を目指した例を記載します。

初めの例ではintervalを引数として使用していたので、今回はby~を使用します。
データは1日分に絞って、LocatorとしてはHourLocatorを使用します。

また、set_major_formatterというぐらいなので、set_minor_formetterを使用することで補助目盛線の設定を行うこともできます。こちらも合わせて確認してみましょう。

# データフレームの準備
start_datetime = datetime.datetime(2017, 11,1, 0, 0,0)
end_datetime = datetime.datetime(2017, 11, 1, 23, 59, 0)
target_df = sample_df[(sample_df["datetime"] >= start_datetime)&(sample_df["datetime"] < end_datetime)]

# 描画
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(target_df["datetime"], target_df["C1"])

# 軸目盛の設定
ax.xaxis.set_major_locator(mdates.HourLocator(byhour=range(0, 24, 3), tz=None))
ax.xaxis.set_minor_locator(mdates.HourLocator(byhour=range(0, 24, 1), tz=None))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d\n%H:%M:%S"))

# 次の2行は軸ラベルを回転させるために使用
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, fontsize=10)

plt.grid(which="both")

描画結果はこちらです。
HourLocator example

Formatterの中身も変えています。

WeekdayLocatorの使用例

今度は、少し変わり種のWeekdayLocatorの例です。
特定の曜日に注目したい場合に役に立ちます。

byweekdayには曜日を示すオブジェクトを渡します。

# データフレームの準備
start_datetime = datetime.datetime(2017, 11,1)
end_datetime = datetime.datetime(2018, 3,1)
target_df = sample_df[(sample_df["datetime"] > start_datetime)&(sample_df["datetime"] < end_datetime)]

# 描画
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(target_df["datetime"], target_df["C1"])

# 目盛の設定
ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MO, tz=None))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))

# 軸目盛ラベルの回転
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, fontsize=10);
ax.grid()

描画結果はこちら。
example of weekday locator

まとめ

横軸に時間をとったグラフを描く際の軸目盛の設定方法をまとめました。
特に注目したい情報がある場合や見え方を整えたい場合は便利だと思います。

参考資料

https://matplotlib.org/api/dates_api.html
https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
https://stackoverflow.com/questions/41953648/matplotlib-with-dates-changing-labels-and-ticks-for-monthly-data
https://stackoverflow.com/questions/25333030/how-do-i-manipulate-datetime-tick-labels-and-limits-on-a-plot-axis-in-python