【保存版】pandasで時系列データ分析を極める!BusinessMonthEndの使い方から応用まで


pandas.tseries.offsets.BusinessMonthEnd は、pandasライブラリにおいて、時系列データの操作に用いられるオフセットの一つです。このオフセットは、月末の最後の営業日に遷移する機能を提供します。つまり、祝日や週末を除いた月末のビジネスデイをターゲット日付とします。

適用例

  • 営業日ベースの指標計算
  • 財務データの分析における月末時点のスナップショット取得
  • 給与支払日などの月末処理を自動化

基本的な使い方

import pandas as pd

# 現在の日付
base_date = pd.Timestamp('2024-06-20')

# 1ヶ月後の月末の営業日
offset = pd.tseries.offsets.BusinessMonthEnd(n=1)
next_business_month_end = base_date + offset

print(next_business_month_end)

上記のコードを実行すると、以下の出力が得られます。

2024-07-31
  • normalize: Trueに設定すると、オフセットが適用される前に日付を月の1日に標準化します。デフォルトはFalseです。
  • n: オフセットの加算回数。デフォルトは1で、1ヶ月後の月末営業日を意味します。
  • 時系列データの操作には、pandas ライブラリ以外にも様々なツールが用意されています。データの性質や目的に応じて適切なツールを選択することが重要です。
  • BusinessMonthEnd オフセットは、米国の祝日カレンダーに基づいています。異なる地域のカレンダーを使用する場合は、CustomBusinessMonthEnd オフセットを用いる必要があります。


特定の日付から翌月末の営業日を取得

import pandas as pd

# 基準日
base_date = pd.Timestamp('2024-06-20')

# 翌月末の営業日
offset = pd.tseries.offsets.BusinessMonthEnd(n=1)
next_business_month_end = base_date + offset

print(next_business_month_end)
2024-07-31

過去nヶ月分の月末営業日をリストに格納

import pandas as pd

# 基準日
base_date = pd.Timestamp('2024-06-20')

# 過去6ヶ月分の月末営業日
offsets = [pd.tseries.offsets.BusinessMonthEnd(n=-i) for i in range(1, 7)]
past_business_month_ends = base_date + offsets

print(past_business_month_ends)

出力

[Timestamp('2024-05-31'), Timestamp('2024-04-30'), Timestamp('2024-03-29'), Timestamp('2024-02-29'), Timestamp('2024-01-31'), Timestamp('2023-12-29')]

特定の月の月末営業日をすべて取得

import pandas as pd

# 対象年
target_year = 2024

# 特定の月の月末営業日
monthly_business_month_ends = []
for month in range(1, 13):
    base_date = pd.Timestamp(f'{target_year}-{month}-1')
    offset = pd.tseries.offsets.BusinessMonthEnd()
    monthly_business_month_ends.append(base_date + offset)

print(monthly_business_month_ends)

出力

[Timestamp('2024-01-31'), Timestamp('2024-02-29'), Timestamp('2024-03-29'), Timestamp('2024-04-30'), Timestamp('2024-05-31'), Timestamp('2024-06-30'), Timestamp('2024-07-31'), Timestamp('2024-08-30'), Timestamp('2024-09-30'), Timestamp('2024-10-31'), Timestamp('2024-11-29'), Timestamp('2024-12-31')]
import pandas as pd
from pandas.tseries.offsets import CustomBusinessMonthEnd

# カスタム祝日カレンダー定義
holidays = pd.to_datetime(['2024-07-04'])  # 例: 7月4日を祝日として定義

offset = CustomBusinessMonthEnd(weekmask='Mon-Fri', holidays=holidays)  # 週の月曜日から金曜日を営業日、7月4日は祝日として設定

# 基準日
base_date = pd.Timestamp('2024-06-20')

# 翌月末の営業日
next_business_month_end = base_date + offset

print(next_business_month_end)

出力

2024-07-31
  • これらの設定により、7月4日は月末であっても営業日ではなく、翌営業日である7月31日が返されます。
  • holidays パラメータで、7月4日を祝日として定義しています。
  • weekmask パラメータで、営業曜日をMon-Fri(月曜日から金曜日)に設定しています。
  • 上記コードでは、CustomBusinessMonthEnd オフセットを用いて、カスタム祝日カレンダーに基づいた月末営業日を計算しています。
  • 複雑な祝日ルールを扱う場合は、専用のライブラリなどを利用するのも有効です。
  • カスタム祝日カレンダーの設定方法は、状況に応じて調整可能です。


MonthEnd + relativedelta

  • 欠点:
    • BusinessMonthEnd オフセットよりも記述が冗長になる
    • relativedelta モジュールのインポートが必要
  • 利点:
    • 祝日カレンダーを柔軟に設定できる
    • 月末以外の特定の日付(例:月末の最初の営業日)を取得できる
  • 方法: pandas.tseries.offsets.MonthEnd オフセットと relativedelta モジュールの relativedelta 関数を組み合わせて使用します。
import pandas as pd
from dateutil.relativedelta import relativedelta

# 基準日
base_date = pd.Timestamp('2024-06-20')

# 翌月末の営業日
offset = MonthEnd() + relativedelta(weekday=relativedelta.FR(1))  # 翌月末の最初の金曜日

next_business_month_end = base_date + offset

print(next_business_month_end)

専用ライブラリ

  • 欠点:
    • 別途ライブラリのインストールが必要
    • pandas の標準機能よりも習得コストがかかる
  • 利点:
    • 祝日カレンダーや週末のルールを詳細に設定できる
    • 複雑なビジネスロジックにも対応できる
  • 方法: bizdayspd-businessdays などの専用ライブラリを使用します。
import pandas as pd
import bizdays

# 基準日
base_date = pd.Timestamp('2024-06-20')

# 翌月末の営業日
offset = bizdays.BMonthEnd()

next_business_month_end = base_date + offset

print(next_business_month_end)

手動で計算

  • 欠点:
    • 煩雑でエラーが発生しやすい
    • スケーラビリティが低い
  • 利点:
    • 処理が軽量
    • 細かい制御が可能
  • 方法: 特定の月のカレンダーを確認し、手動で月末の営業日を算出します。
import pandas as pd

# 基準日
base_date = pd.Timestamp('2024-06-20')

# 対象年と月
target_year = 2024
target_month = 7

# 特定の月のカレンダーを取得
calendar = pd.date_range(start=f'{target_year}-{target_month}-01', end=f'{target_year}-{target_month}-31', freq='D')

# 月末の営業日
business_month_end = calendar[calendar.is_weekday & ~calendar.isin(['2024-07-04'])]  # 例:7月4日は祝日として除外

print(business_month_end[-1])
  • 制御性: 細かい制御が必要であれば、手動での計算が適しています。
  • 処理速度: 処理速度が重要であれば、BusinessMonthEnd オフセットがおすすめです。
  • 柔軟性: 祝日カレンダーや週末のルールを詳細に設定したい場合は、MonthEnd + relativedelta または専用ライブラリが適しています。
  • シンプルさ: BusinessMonthEnd オフセットが最もシンプルで汎用性が高いです。
  • 最適な方法は、データの性質や目的に応じて選択することが重要です。
  • 上記以外にも、状況に応じて様々な代替方法が考えられます。