Pandas Data Offsetsで日付データを操作: BusinessMonthBeginを徹底解説

2024-06-17

Pandas の Data Offsets における BusinessMonthBegin

pandas.tseries.offsets.BusinessMonthBegin は、Pandas DataFrames で日付データを操作するために使用されるオフセットクラスの一つです。このオフセットは、月初めの最初の営業日 に移動します。つまり、祝日や週末を除いた最初の平日 を指します。

使い方

BusinessMonthBegin オフセットは、以下の方法で使用できます。

  • DataFrame の列にオフセットを設定:
import pandas as pd

# データフレームの作成
df = pd.DataFrame({'date': pd.date_range('2023-01-01', periods=12)})

# BusinessMonthBegin オフセットを設定
df['next_month_begin'] = df['date'] + pd.tseries.offsets.BusinessMonthBegin(1)

print(df)

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

        date        next_month_begin
0    2023-01-01    2023-02-01
1    2023-02-01    2023-03-01
2    2023-03-01    2023-04-03
3    2023-04-01    2023-05-01
4    2023-05-01    2023-06-01
5    2023-06-01    2023-07-03
6    2023-07-01    2023-08-01
7    2023-08-01    2023-09-04
8    2023-09-01    2023-10-02
9    2023-10-02    2023-11-01
10   2023-11-01    2023-12-04
11   2023-12-04    2024-01-02
  • 日付操作:
import pandas as pd

# 基準日
base_date = pd.Timestamp('2023-01-01')

# BusinessMonthBegin オフセットを使用して 1 か月後の日付を取得
next_month_begin = base_date + pd.tseries.offsets.BusinessMonthBegin(1)

print(next_month_begin)
2023-02-01 00:00:00

注意点

  • BusinessMonthBegin オフセットは、米国市場の営業日 を基準としています。他の地域の営業日を使用する場合は、start_dayweekdays などのオプションを設定する必要があります。
  • 祝日は考慮されますが、土曜日 が祝日の場合は、次の月曜日 がオフセットとして返されます。
  • BusinessMonthBegin オフセットは、BMonthBegin というエイリアスも持っています。

補足情報

  • Pandas には、BusinessDayOffsetBusinessHourOffset など、他にもさまざまな Data Offsets クラスがあります。
  • Data Offsets は、時間経過とともに変化するデータ (株価、為替レートなど) を分析する際に役立ちます。


    特定の祝日を考慮した BusinessMonthBegin オフセットの使用

    import pandas as pd
    from pandas.tseries.offsets import BusinessMonthBegin
    
    # 基準日
    base_date = pd.Timestamp('2022-12-31')
    
    # 2023年の元旦を祝日として定義
    holidays = pd.to_datetime(['2023-01-01'])
    
    # BusinessMonthBegin オフセット (2023年の元旦を考慮)
    offset = BusinessMonthBegin(1, holidays=holidays)
    
    # 次の月初めの日付
    next_month_begin = base_date + offset
    
    print(next_month_begin)
    

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

    2023-02-01 00:00:00
    

    週末を含む BusinessMonthBegin オフセットの使用

    BusinessMonthBegin オフセットはデフォルトで週末を除外しますが、weekends オプションを使用して週末を含めることができます。 以下のコードは、2023年1月1日から1ヶ月後のすべての週末を含む日付のリストを作成する例です。

    import pandas as pd
    from pandas.tseries.offsets import BusinessMonthBegin
    
    # 基準日
    base_date = pd.Timestamp('2023-01-01')
    
    # 週末を含む BusinessMonthBegin オフセット
    offset = BusinessMonthBegin(1, weekends=True)
    
    # 次の月までのすべての週末の日付
    dates = []
    while base_date < base_date + offset(base_date):
        dates.append(base_date)
        base_date += offset
    
    print(dates)
    
    [Timestamp('2023-01-01 00:00:00'), Timestamp('2023-01-06 00:00:00'), Timestamp('2023-01-13 00:00:00'), Timestamp('2023-01-20 00:00:00'), Timestamp('2023-01-27 00:00:00'), Timestamp('2023-02-03 00:00:00'), Timestamp('2023-02-10 00:00:00'), Timestamp('2023-02-17 00:00:00'), Timestamp('2023-02-24 00:00:00')]
    

    異なる地域の営業日基準の BusinessMonthBegin オフセットの使用

    BusinessMonthBegin オフセットは米国の営業日基準ですが、start_day オプションを使用して異なる地域の営業日基準を設定することができます。 以下のコードは、日本市場の営業日基準で1ヶ月後のオフセットを返す例です。

    import pandas as pd
    from pandas.tseries.offsets import BusinessMonthBegin
    
    # 基準日
    base_date = pd.Timestamp('2023-01-01')
    
    # 日本市場の営業日基準 (月曜から金曜)
    offset = BusinessMonthBegin(1, start_day='mon', weekmask='Mon-Fri')
    
    # 次の月初めの日付 (日本市場の営業日基準)
    next_month_begin = base_date + offset
    
    print(next_month_begin)
    
    2023-02-06 00:00:00
    

    補足

    • 上記のコードはほんの一例です。ご自身のニーズに合わせてカスタマイズすることができます。


    pandas.tseries.offsets.BusinessMonthBegin の代替方法

    手動でオフセットを計算する

    最も基本的な方法は、手動でオフセットを計算することです。 以下のコードは、datetime モジュールと calendar モジュールを使用して、2023年1月1日から1ヶ月後の最初の営業日を計算する例です。

    import datetime
    import calendar
    
    def next_business_day(date):
        date += datetime.timedelta(days = 1)
        while date.weekday() in (calendar.SATURDAY, calendar.SUNDAY):
            date += datetime.timedelta(days = 1)
        return date
    
    base_date = datetime.datetime(2023, 1, 1)
    next_month_begin = next_business_day(base_date + relativedelta.relativedelta(months=+1))
    
    print(next_month_begin)
    

    この方法の長所は、柔軟性に優れていることです。 独自のルールに基づいてオフセットを計算することができます。 一方、短所は、コードが煩雑になり、エラーが発生しやすいことです。

    カスタムオフセットクラスを作成する

    より柔軟な代替方法として、カスタムオフセットクラスを作成することができます。 以下のコードは、BMonthBegin という名前のカスタムオフセットクラスを作成する例です。 このオフセットクラスは、BusinessMonthBegin と同様に動作しますが、start_dayweekmask などのオプションを追加することができます。

    from pandas import offsets
    import pandas as pd
    
    class BMonthBegin(offsets.Offset):
    
        def __init__(self, start_day=1, weekmask='Mon-Fri'):
            self.start_day = start_day
            self.weekmask = weekmask
    
        def __repr__(self):
            return f'BMonthBegin(start_day={self.start_day}, weekmask={self.weekmask})'
    
        def rollforward(self, basedate):
            if basedate.weekday() == self.start_day:
                return basedate + relativedelta.relativedelta(months=+1)
            else:
                offset_days = (self.start_day - basedate.weekday()) % 7
                return basedate + relativedelta.relativedelta(days=+offset_days, months=+1)
    
    base_date = pd.Timestamp('2023-01-01')
    offset = BMonthBegin(start_day=1, weekmask='Mon-Fri')
    next_month_begin = base_date + offset
    
    print(next_month_begin)
    

    この方法の長所は、BusinessMonthBegin よりも柔軟性に優れていることです。 独自のルールに基づいてオフセットを定義することができます。 一方、短所は、コード作成に時間がかかり、複雑になることです。

    サードパーティライブラリを使用する

    BusinessMonthBegin の代替となるサードパーティライブラリがいくつかあります。 例えば、dateutil ライブラリには、relativedelta モジュールが提供されており、月初めの最初の営業日を計算するための機能が含まれています。 以下のコードは、dateutil ライブラリを使用して2023年1月1日から1ヶ月後の最初の営業日を計算する例です。

    from dateutil.relativedelta import relativedelta
    import pandas as pd
    
    base_date = pd.Timestamp('2023-01-01')
    offset = relativedelta(months=+1, weekday=relativedelta.MO(1))
    next_month_begin = base_date + offset
    
    print(next_month_begin)
    

    この方法の長所は、簡単に使用できることです。 サードパーティライブラリがすでに必要な機能を提供している場合、この方法が最適です。 一方、短所は、すべての環境で利用可能とは限らないことです。

    pandas.tseries.offsets.BusinessMonthBegin の代替方法はいくつかありますが、それぞれ長所と短所があります。 ご自身のニーズに合った方法を選択してください。

    補足

    • 上記のコードはほんの一例です。ご自身のニーズに合わせてカスタマイズすることができます。