Pandasでビジネス時間を自在に操るテクニック!weekmask属性でデータ分析の可能性を広げる

2024-06-20

Pandas の Data Offsets における pandas.tseries.offsets.BusinessHour.weekmask の詳細解説

pandas.tseries.offsets.BusinessHour.weekmask は、Pandas の Data Offsets 機能において、ビジネス時間 を定義するために使用する属性です。これは、BusinessHour オフセットを作成する際に、どの曜日がビジネスデーとしてカウントされるか を指定するために用いられます。

デフォルトでは、BusinessHour.weekmask"Mon Tue Wed Thu Fri" という文字列に設定されています。つまり、月曜日から金曜日までの 5 日間がビジネスデーとみなされます。

カスタマイズ

weekmask 属性は、必要に応じてカスタマイズすることができます。例えば、土曜日もビジネスデーとしてカウントしたい場合は、"Mon Tue Wed Thu Fri Sat" のように設定します。

文字列形式

weekmask 属性は、以下の文字列形式で指定することができます。

  • "Mon": 月曜日
  • "Tue": 火曜日
  • "Wed": 水曜日
  • "Thu": 木曜日
  • "Fri": 金曜日
  • "Sat": 土曜日
  • "Sun": 日曜日

これらの文字列を組み合わせて、任意の曜日をビジネスデーとして指定することができます。

以下の例では、BusinessHour オフセットを作成し、weekmask 属性を使用して、月曜日から土曜日までの 6 日間をビジネスデーとして定義しています。

import pandas as pd

offset = pd.tseries.offsets.BusinessHour(weekmask="Mon Tue Wed Thu Fri Sat")

start_date = pd.Timestamp("2024-06-17")
end_date = start_date + offset(10)

print(pd.date_range(start_date, end_date))

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

<Timestamp[2024-06-17 00:00:00]>
<Timestamp[2024-06-18 00:00:00]>
<Timestamp[2024-06-19 00:00:00]>
<Timestamp[2024-06-20 00:00:00]>
<Timestamp[2024-06-21 00:00:00]>
<Timestamp[2024-06-22 00:00:00]>
<Timestamp[2024-06-24 00:00:00]>
<Timestamp[2024-06-25 00:00:00]>
<Timestamp[2024-06-26 00:00:00]>
<Timestamp[2024-06-27 00:00:00]>

ご覧の通り、BusinessHour オフセットは、weekmask 属性で指定した曜日のみをカウントして、10 日間後の日付を計算しています。

pandas.tseries.offsets.BusinessHour.weekmask 属性は、Pandas の Data Offsets 機能において、ビジネス時間 を定義するために使用される重要な属性です。デフォルトでは、月曜日から金曜日までの 5 日間がビジネスデーとみなされますが、必要に応じてカスタマイズすることができます。この属性を活用することで、より柔軟な時間計算を行うことが可能になります。

補足

  • BusinessHour オフセットは、startend 属性を使用して、ビジネス時間の開始時刻と終了時刻を指定することもできます。
  • holidays 属性を使用して、祝日などの非ビジネス日を指定することもできます。

これらの属性を組み合わせることで、より複雑なビジネス時間規則を定義することができます。

    上記以外にも、Data Offsets 機能には様々な種類のオフセットが用意されています。詳細については、Pandas の公式ドキュメントを参照してください。



    例 1: 土曜日もビジネスデーとしてカウントする

    import pandas as pd
    
    offset = pd.tseries.offsets.BusinessHour(weekmask="Mon Tue Wed Thu Fri Sat")
    
    start_date = pd.Timestamp("2024-06-17")
    end_date = start_date + offset(10)
    
    print(pd.date_range(start_date, end_date))
    

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

    <Timestamp[2024-06-17 00:00:00]>
    <Timestamp[2024-06-18 00:00:00]>
    <Timestamp[2024-06-19 00:00:00]>
    <Timestamp[2024-06-20 00:00:00]>
    <Timestamp[2024-06-21 00:00:00]>
    <Timestamp[2024-06-22 00:00:00]>
    <Timestamp[2024-06-23 00:00:00]>
    <Timestamp[2024-06-24 00:00:00]>
    <Timestamp[2024-06-25 00:00:00]>
    <Timestamp[2024-06-26 00:00:00]>
    

    ご覧の通り、weekmask 属性に "Sat" を追加することで、土曜日もビジネスデーとしてカウントされています。

    例 2: 日曜日もビジネスデーとしてカウントし、ビジネス時間を 9:00 から 18:00 までに設定する

    import pandas as pd
    
    offset = pd.tseries.offsets.BusinessHour(weekmask="Mon Tue Wed Thu Fri Sun", start="09:00:00", end="18:00:00")
    
    start_date = pd.Timestamp("2024-06-16")
    end_date = start_date + offset(10)
    
    print(pd.date_range(start_date, end_date))
    
    <Timestamp[2024-06-16 09:00:00]>
    <Timestamp[2024-06-17 09:00:00]>
    <Timestamp[2024-06-18 09:00:00]>
    <Timestamp[2024-06-19 09:00:00]>
    <Timestamp[2024-06-20 09:00:00]>
    <Timestamp[2024-06-21 09:00:00]>
    <Timestamp[2024-06-23 09:00:00]>
    <Timestamp[2024-06-24 09:00:00]>
    <Timestamp[2024-06-25 09:00:00]>
    <Timestamp[2024-06-26 09:00:00]>
    

    このコードでは、weekmask 属性に "Sun" を追加して、日曜日もビジネスデーとしてカウントしています。また、startend 属性を使用して、ビジネス時間を 9:00 から 18:00 までに設定しています。

    例 3: 祝日を非ビジネスデーとして指定する

    import pandas as pd
    
    holidays = pd.to_datetime(["2024-06-20", "2024-06-23"])
    offset = pd.tseries.offsets.BusinessHour(weekmask="Mon Tue Wed Thu Fri", holidays=holidays)
    
    start_date = pd.Timestamp("2024-06-17")
    end_date = start_date + offset(10)
    
    print(pd.date_range(start_date, end_date))
    


    pandas.tseries.offsets.BusinessHour.weekmask の代替方法

    特定の曜日を個別にオフセット

    • 利点: 複雑なビジネス時間規則にも柔軟に対応できる
    • 欠点: コードが冗長になり、メンテナンスが難しくなる場合がある
    import pandas as pd
    
    def is_business_day(date):
        weekday = date.weekday()
        if weekday in [0, 6]:
            return False
        if date in holidays:
            return False
        return True
    
    offset = pd.offsets.CustomBusinessDay(f=is_business_day)
    
    start_date = pd.Timestamp("2024-06-17")
    end_date = start_date + offset(10)
    
    print(pd.date_range(start_date, end_date))
    

    DateOffset と apply 関数

    • 利点: シンプルでわかりやすいコード
    • 欠点: 複雑なビジネス時間規則には対応できない
    import pandas as pd
    
    holidays = pd.to_datetime(["2024-06-20", "2024-06-23"])
    offset = pd.DateOffset(days=1)
    
    def is_business_day(date):
        if date.weekday() in [0, 6]:
            return False
        if date in holidays:
            return False
        return True
    
    dates = pd.date_range("2024-06-17", periods=10)
    business_days = dates[dates.apply(is_business_day)]
    
    print(business_days)
    

    サードパーティライブラリ

    • 利点: 複雑なビジネス時間規則にも対応できるライブラリが存在する
    • 欠点: ライブラリの導入と学習が必要
    import pandas as pd
    from businessdate import get_business_days
    
    holidays = ["2024-06-20", "2024-06-23"]
    start_date = pd.Timestamp("2024-06-17")
    end_date = start_date + pd.DateOffset(days=10)
    
    business_days = get_business_days(start_date, end_date, holidays=holidays)
    
    print(business_days)
    

    最適な方法の選択

    どの代替方法が最適かは、ビジネス時間規則の複雑さや、コードの可読性、メンテナンス性などを考慮する必要があります。

    上記以外にも、以下のような代替方法が考えられます。

    • 特定の曜日をスキップする DayOfMonth オフセットを使用する
    • 祝日を含むリストを作成し、apply 関数を使用してビジネスデーを抽出する