日付データの周期性抽出方法

この記事では、特徴量として日付や時刻などの情報を扱う際に、周期性・循環性を考慮するための方法について説明します。
はじめに
日付や時間のデータは、実際には連続的であっても、データ上では非連続的に表現されることがよく見られます。そこで本記事では、三角関数変換を使用して周期性を抽出する方法について焦点を当てて説明します。
なぜ三角関数による変換する必要があるのか?
日付を例に考えてみると、2023-12-31(12月31日)の次は、2024-01-01(1月1日)ですが、データ上ではこの間には数値的な繋がりはありません。そのため、日付のみを特徴として使用した際、日付や時間の持つ周期性や循環性などの時間的な繋がりが途絶えてしまいます。
この問題について、三角関数を用いて解決していきます。
今回は例として、1年周期や1ヶ月周期、1週間周期で周期性を考慮した特徴の作成を行います。
実際にやってみる
日付データの生成
今回は、2023-01-01から2023-03-31までの日付のデータを用意して、三角関数変換を行ってみます。
まずは、日付データの生成を行います。
import pandas as pd
import numpy as np
# 2023年1月1日から2023年12月31日までの日付データを生成(時刻データは含まない)
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
df = pd.DataFrame({'dates': dates})
三角関数変換による1ヶ月周期の周期性の抽出
ここで、1月から3月までの日付のデータをプロットして、確認してみます。
このようになっており、月が切り替わると日付の連続性が失われていることがわかります。このまま日付データを特徴量として扱うと、1月31日と2月1日のような部分で、実際には、1月31日の次の日が2月1日であるのに、データ上、繋がりがないものとして扱ってしまいます。
そこで次は、三角関数変換を用いて、実際に周期性が考慮できるのか、実際に確かめてみましょう。
日付データを、1ヶ月1周期として三角関数変換するコードを以下に示します。
def create_monthly_daily_trigonometric_data(df):
df['days_in_month'] = df['dates'].dt.days_in_month
df['day_of_month'] = df['dates'].dt.day
# 月の日数に基づいて三角関数の値を計算
df['sin_month'] = np.sin(2 * np.pi * (df['day_of_month'] - 1) / df['days_in_month'])
df['cos_month'] = np.cos(2 * np.pi * (df['day_of_month'] - 1) / df['days_in_month'])
return df
# 月周期の三角関数データを作成
df = create_monthly_daily_trigonometric_data(df)
ここで、1月から3月までの三角関数に変換した日付の値をプロットしてみます。
高校数学で学習した三角関数のsin, cosの波形が見られます。これにより、日付データが、1ヶ月の周期性をもって扱うことができるようになりました。
1月31日と2月1日を例に見ると、三角関数を用いない場合は、データに連続性がありませんでしたが、三角関数変換をした場合には、データに連続性・循環性があることがわかります。
週単位での周期性の抽出
次は同様に、日付の情報を、週単位で1週間(7日間)を1周期として三角関数変換するコードを以下に示します。
def create_weekly_trigonometric_data(df):
df['day_of_week'] = df['dates'].dt.dayofweek
# 週の周期(月曜日を周期の始点とする)
df['sin_week'] = np.sin(2 * np.pi * df['day_of_week'] / 7)
df['cos_week'] = np.cos(2 * np.pi * df['day_of_week'] / 7)
return df
# 月周期の三角関数データを作成
df = create_weekly_trigonometric_data(df)
2023年1月における、曜日の値(day_of_weekにより日付から曜日を0~6の値に変換したもの)と、day_of_weekの値に三角関数変換を適用したものを比較すると以下のようになります。
2023年1月におけるday_of_weekの値をプロット
2023年1月におけるday_of_weekの値を三角関数変換した値をプロット
以上の二つを比較すると、三角関数変換しない場合は、日曜日(day_of_week = 6 )と月曜日(day_of_week = 0 )が繋がりがなくなっていることがわかりますが、三角関数変換を用いた場合は、周期性があることがわかります。
年単位での周期性の抽出
最後に、年単位での周期性について、考えてみましょう。
年単位で、1年(365日)を1周期として三角関数変換するコードを以下に示します。
def create_yearly_trigonometric_data(df):
df['days_in_year'] = 365
df['day_of_year'] = df['dates'].dt.dayofyear
# 年周期の三角関数
df['sin_year'] = np.sin(2 * np.pi * (df['day_of_year'] - 1) / df['days_in_year'])
df['cos_year'] = np.cos(2 * np.pi * (df['day_of_year'] - 1) / df['days_in_year'])
return df
# 年周期と月周期の三角関数データを作成
df = create_yearly_trigonometric_data(df)
2023年における日付の値をプロット
2023年における日付の値を1年を1周期で三角関数変換した値をプロット
このように、1年を1周期とした際も同様に、三角関数を用いて変換することで、データ上では繋がりがないような12月31日と1月1日が連続的に扱うことが可能であることがわかります。
おわりに
今回は、日付データの周期性と循環性を抽出する方法として、三角関数を使用する方法を説明しました。
日付や時間データが、よく非連続的な数値として扱われることに対し、三角関数変換を使用することで、これらのデータの持つ本来の周期性や循環性を捉えることが可能であることがわかりました。このアプローチは、時系列データや季節性を持つデータの分析において、より精度の高いモデリングや予測を活用できます!