matplotlibでX軸が日付のグラフを描く

Pythonで時系列のデータを扱っていると、X軸が日付のグラフを描くことってありますよね。やってみました。

X軸を日付にすると、値がない日付のスペース分が飛ばされて、日付の間隔がちゃんとグラフに反映されるから便利です。プロット間隔が実際の時間軸の間隔と同じになるイメージです。

グラフ化データの作成

日付データ

日付データはpandas.date_range関数で作成します。1日単位で1ヶ月分の日付を作成しました。

# 日付を作成する。
t = pd.date_range(
    start='2024-10-01',
    end='2024-11-01',
    freq='D',
    inclusive='left', # endの日付は含めない。
    )

print(t)
print(type(t))
print(len(t))
# DatetimeIndex(['2024-10-01', '2024-10-02', '2024-10-03', '2024-10-04',
#                '2024-10-05', '2024-10-06', '2024-10-07', '2024-10-08',
#                '2024-10-09', '2024-10-10', '2024-10-11', '2024-10-12',
#                '2024-10-13', '2024-10-14', '2024-10-15', '2024-10-16',
#                '2024-10-17', '2024-10-18', '2024-10-19', '2024-10-20',
#                '2024-10-21', '2024-10-22', '2024-10-23', '2024-10-24',
#                '2024-10-25', '2024-10-26', '2024-10-27', '2024-10-28',
#                '2024-10-29', '2024-10-30', '2024-10-31'],
#               dtype='datetime64[ns]', freq='D')
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
# 31

プロットする値の作成

プロットする値は、連続する整数をリスト内包表記で作成しました。

# 日付分の整数の配列を作成する。
v = [x for x in range(len(t))]

print(v)
print(len(v))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
# 31

今回のサンプルコードでは使いませんでしたが、整数の乱数を使ってもいいと思います。

# 0から100の間の整数の乱数の配列を作成する。
v = [random.randint(0, 100) for x in range(len(t))]

print(v)
print(len(v))
# [78, 37, 34, 41, 90, 28, 2, 6, 66, 4, 86, 45, 15, 27, 22, 52, 68, 25, 85, 37, 75, 9, 45, 14, 70, 71, 0, 31, 45, 27, 12]
# 31

DataFrame.plotで描く

DataFrame.plotを使ってグラフを描きます。
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html

# 日付を作成する。
t = pd.date_range(
    start='2024-10-01',
    end='2024-11-01',
    freq='D',
    inclusive='left', # endの日付は含めない。
    )


# 日付分の整数の配列を作成する。
v = [x for x in range(len(t))]


# DataFrameにする。
df = pd.DataFrame(
    data=v,
    index=t,
    columns=['value'])

# データ後半は日付の間隔を空ける。
df = pd.concat([df.iloc[:15:], df.iloc[15::3]], axis='index')

print(df)
#             value
# 2024-10-01      0
# 2024-10-02      1
# 2024-10-03      2
# 2024-10-04      3
# 2024-10-05      4
# 2024-10-06      5
# 2024-10-07      6
# 2024-10-08      7
# 2024-10-09      8
# 2024-10-10      9
# 2024-10-11     10
# 2024-10-12     11
# 2024-10-13     12
# 2024-10-14     13
# 2024-10-15     14
# 2024-10-16     15
# 2024-10-19     18
# 2024-10-22     21
# 2024-10-25     24
# 2024-10-28     27
# 2024-10-31     30


# 描画する。
fig = plt.figure()
ax = fig.add_subplot()
df.plot(ax=ax, marker='.', alpha=0.5)
plt.show()

グラフはこのようになります。データ後半は日付の間隔を広げましたが、そのようにプロットされています。

ax.plotで描く

ax.plotを使ってグラフを描きます。グラフ化する内容は、上のコードと同じです。
https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html

# 日付を作成する。
t = pd.date_range(
    start='2024-10-01',
    end='2024-11-01',
    freq='D',
    inclusive='left', # endの日付は含めない。
    )

# 日付分の整数の配列を作成する。
v = [x for x in range(len(t))]

# データ後半は日付の間隔を空ける。
t = list(t)[:15:] + list(t)[15::3]
v = v[:15:] + v[15::3]

# 描画する。
fig = plt.figure()
ax = fig.add_subplot()
ax.plot(t, v, marker='.', alpha=0.5)

# X軸のラベルが重なって潰れたので、自動整形する。
fig.autofmt_xdate()
plt.show()

グラフはこのようになります。上のグラフとほぼ同じですが、デフォルトだと凡例が表示されないようです。