Loading [MathJax]/extensions/tex2jax.js

[matplotlib] 54. ConciseDateFormatterで時系列グラフの軸ラベルをシンプルにする

matplotlib

はじめに

matplotlib.datesのConciseDateFormatterで時系列グラフの目盛りラベルを簡潔に表示する方法について説明する。

コード

#ConciseDateFormatterを使用した日付フォーマット変更
%matplotlib inline
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
#the default formatter
base = datetime.datetime(2019, 10, 1)
dates = np.array([base + datetime.timedelta(hours=(0.5*i))
for i in range(24*256)])
N = len(dates)
np.random.seed(19423521)
y = np.cumsum(np.random.randn(N))
lims = [(np.datetime64('2019-10'), np.datetime64('2020-02')),
(np.datetime64('2019-12-03'), np.datetime64('2019-12-15')),
(np.datetime64('2019-12-03 13:00'), np.datetime64('2019-12-04 13:00')),
(np.datetime64('2019-12-03 11:00'), np.datetime64('2019-12-03 11:01'))]
fig, axs = plt.subplots(4, 1, constrained_layout=True, figsize=(6, 8))
for nn, ax in enumerate(axs):
locator = mdates.AutoDateLocator(minticks=4, maxticks=9)
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(dates, y,'g-')
ax.set_xlim(lims[nn])
axs[0].set_title('Concise Date Formatter')
plt.savefig("Concisedateformatter.png", dpi=100,transparent = False, bbox_inches = 'tight')
plt.show()

解説

モジュールのインポート

%matplotlib inline
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np

バージョン

#version
import matplotlib
print(matplotlib.__version__)
3.3.4
print(np.__version__)
1.20.1
print(pd.__version__)
1.2.3

データの生成

base = datetime.datetime(2019, 10, 1)
dates = np.array([base + datetime.timedelta(hours=(0.5*i))
for i in range(24*256)])
N = len(dates)
np.random.seed(19423521)
y = np.cumsum(np.random.randn(N))

dates = np.array([base + datetime.timedelta(hours=(0.5*i)) for i in range(24*256)])で baseの日付から、0.5h刻みで24 ✕256 = 6144回時間を増加させた配列が得られる。

表示範囲の設定

lims = [(np.datetime64('2019-10'), np.datetime64('2020-02')),
(np.datetime64('2019-12-03'), np.datetime64('2019-12-15')),
(np.datetime64('2019-12-03 13:00'), np.datetime64('2019-12-04 13:00')),
(np.datetime64('2019-12-03 11:00'), np.datetime64('2019-12-03 11:01'))]

デフォルト設定の時系列グラフ

fig, axs = plt.subplots(4, 1, constrained_layout=True, figsize=(6, 8))
lims = [(np.datetime64('2019-10'), np.datetime64('2020-02')),
(np.datetime64('2019-12-03'), np.datetime64('2019-12-15')),
(np.datetime64('2019-12-03 13:00'), np.datetime64('2019-12-04 13:00')),
(np.datetime64('2019-12-03 11:00'), np.datetime64('2019-12-03 11:01'))]
for nn, ax in enumerate(axs):
ax.plot(dates, y,'g-')
ax.set_xlim(lims[nn])
# rotate_labels...
for label in ax.get_xticklabels():
label.set_rotation(30)
label.set_horizontalalignment('right')
axs[0].set_title('Default Date Formatter')
plt.savefig("defaultdateformatter.png", dpi=100,transparent = False, bbox_inches = 'tight')
plt.show()

時間の表示範囲によって目盛りラベルが変化するが基本的にどれも長いので、重なりを防ぐ必要がある。ここでは、label.set_rotation(30)で30°回転している。

ConciseDateFormatterを使った時系列グラフ

fig, axs = plt.subplots(4, 1, constrained_layout=True, figsize=(6, 8))
for nn, ax in enumerate(axs):
locator = mdates.AutoDateLocator(minticks=4, maxticks=9)
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(dates, y,'g-')
ax.set_xlim(lims[nn])
axs[0].set_title('Concise Date Formatter')
plt.savefig("Concisedateformatter.png", dpi=100,transparent = False, bbox_inches = 'tight')
plt.show()

最初に、locator = mdates.AutoDateLocator(minticks=4, maxticks=9)で目盛りの数などを決め、
formatter = mdates.ConciseDateFormatter(locator)により、ConciseDateFormatterlocatorに適用する。
グラフに設定を反映させるには、ax.xaxis.set_major_locator(locator)ax.xaxis.set_major_formatter(formatter)とする必要がある。

units registryを使ってConciseDateFormatterを適用させる方法

import matplotlib.units as munits
converter = mdates.ConciseDateConverter()
munits.registry[np.datetime64] = converter
munits.registry[datetime.date] = converter
munits.registry[datetime.datetime] = converter
fig, axs = plt.subplots(4, 1, figsize=(6, 8), constrained_layout=True)
for nn, ax in enumerate(axs):
ax.plot(dates, y,'g-')
ax.set_xlim(lims[nn])
axs[0].set_title('Concise Date Formatter')
plt.savefig("Concisedateformatter_regist.png", dpi=100,transparent = False, bbox_inches = 'tight')
plt.show()

converter = mdates.ConciseDateConverter()とし、munits.registry[np.datetime64] = converterとしておけば、set_major_formatterなどをする必要がないので、より簡単に軸ラベルを簡素化できる。

コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

Formatting date ticks using ConciseDateFormatter — Matplotlib 3.4.3 documentation

コメント