Pandasでビジネス時間を自在に操るテクニック!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 属性は、以下の文字列形式で指定することができます。

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

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

以下の例では、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 日間がビジネスデーとみなされますが、必要に応じてカスタマイズすることができます。この属性を活用することで、より柔軟な時間計算を行うことが可能になります。

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

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



例 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 までに設定しています。

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))


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

  • 欠点: コードが冗長になり、メンテナンスが難しくなる場合がある
  • 利点: 複雑なビジネス時間規則にも柔軟に対応できる
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)

最適な方法の選択

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

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

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