Pandasで時系列差分インデックスの頻度を賢く推測: `pandas.TimedeltaIndex.inferred_freq`徹底解説


pandas.TimedeltaIndex.inferred_freq は、TimedeltaIndex オブジェクトの推定頻度を表す文字列を返します。これは、TimedeltaIndex オブジェクトの値間の差が一定かどうかを判断し、その差に基づいて頻度を推定するものです。

詳細

TimedeltaIndex オブジェクトは、時系列データの差分を表すデータ構造です。各要素は、前の要素との時間差を表す timedelta オブジェクトです。inferred_freq 属性は、この差分に基づいて推定される頻度を表します。

推定頻度の種類

推定される頻度は、以下のいずれかになります。

  • 'ns': すべての差分が 1 ナノ秒の場合
  • 'U': すべての差分が 1 マイクロ秒の場合
  • 'L': すべての差分が 1 ミリ秒の場合
  • 'S': すべての差分が 1 秒の場合
  • 'T': すべての差分が 1 分の場合
  • 'H': すべての差分が 1 時間の場合
  • 'D': すべての差分が 1 日の場合
  • 'B': すべての差分が 1 ビジネスデーの場合
  • 'N': すべての差分が同じ場合 (N は差分の値)
  • None: 頻度を推定できない場合

推定頻度の判断

inferred_freq 属性は、以下の手順で推定されます。

  1. すべての差分が同じかどうかを確認します。同じ場合は、その値を N として返します。
  2. すべての差分が 1 ビジネスデーかどうかを確認します。同じ場合は、'B' を返します。
  3. すべての差分が 1 日かどうかを確認します。同じ場合は、'D' を返します。
  4. ... (同様の手順で 'H', 'T', 'S', 'L', 'U', 'ns' を確認)
  5. 上記のいずれにも該当しない場合は、None を返します。

import pandas as pd

# 1 日おきの時間差の TimedeltaIndex を作成
tdidx = pd.TimedeltaIndex([pd.Timedelta('1 days'), pd.Timedelta('2 days'), pd.Timedelta('3 days')])

# 推定頻度を取得
print(tdidx.inferred_freq)

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

D

これは、TimedeltaIndex オブジェクトのすべての差分が 1 日であるため、推定頻度が 'D' になることを意味します。



異なる頻度の TimedeltaIndex を作成

import pandas as pd

# 1 日おきの時間差の TimedeltaIndex
tdidx1 = pd.TimedeltaIndex([pd.Timedelta('1 days'), pd.Timedelta('2 days'), pd.Timedelta('3 days')])

# 12 時間おきの時間差の TimedeltaIndex
tdidx2 = pd.TimedeltaIndex([pd.Timedelta('12 hours'), pd.Timedelta('24 hours'), pd.Timedelta('36 hours')])

# 1 分おきの時間差の TimedeltaIndex
tdidx3 = pd.TimedeltaIndex([pd.Timedelta('1 minutes'), pd.Timedelta('2 minutes'), pd.Timedelta('3 minutes')])

# 推定頻度を表示
print(tdidx1.inferred_freq)  # 'D'
print(tdidx2.inferred_freq)  # 'H'
print(tdidx3.inferred_freq)  # 'T'
D
H
T

それぞれの TimedeltaIndex オブジェクトの推定頻度が、正しく推定されていることが確認できます。

推定頻度が None になる場合

import pandas as pd

# ランダムな時間差の TimedeltaIndex
tdidx = pd.TimedeltaIndex([pd.Timedelta('10 seconds'), pd.Timedelta('2 minutes'), pd.Timedelta('3 hours')])

# 推定頻度を表示
print(tdidx.inferred_freq)
None

これは、TimedeltaIndex オブジェクトの差分がランダムなため、推定頻度を特定できないことを意味します。

import pandas as pd

# 1 日おきの時間差の TimedeltaIndex
tdidx = pd.TimedeltaIndex([pd.Timedelta('1 days'), pd.Timedelta('2 days'), pd.Timedelta('3 days')])

# 頻度を 'H' (1 時間) に設定
tdidx = tdidx.to_freq('H')

# 推定頻度を表示
print(tdidx.inferred_freq)
H


より正確な方法として、以下の代替方法を検討することができます。

to_freq() メソッドを使用する

to_freq() メソッドを使用すると、TimedeltaIndex オブジェクトの頻度を明示的に設定することができます。

import pandas as pd

# 1 日おきの時間差の TimedeltaIndex
tdidx = pd.TimedeltaIndex([pd.Timedelta('1 days'), pd.Timedelta('2 days'), pd.Timedelta('3 days')])

# 頻度を 'H' (1 時間) に設定
tdidx = tdidx.to_freq('H')

# 各要素の時間差を取得
print(tdidx.hour)
0 0 0
Name: hour, dtype: int64

to_freq() メソッドを使用すると、推定ではなく、設定した値に基づいた正確な頻度を取得することができます。

df.diff() メソッドと df.dropna() メソッドを使用する

df.diff() メソッドと df.dropna() メソッドを使用して、差分と欠損値を除去することで、頻度を推定することができます。

import pandas as pd

# ランダムな時間差の TimedeltaIndex
tdidx = pd.TimedeltaIndex([pd.Timedelta('10 seconds'), pd.Timedelta('2 minutes'), pd.Timedelta('3 hours')])

# 差分を取得
diffs = tdidx.diff()

# 欠損値を除去
diffs = diffs.dropna()

# 最小公倍数を求める
freq = pd.api.types.common.gcd(*diffs)

# 頻度を文字列に変換
freq_str = str(freq).lower() + (freq.unit if freq.unit else '')

# 推定頻度を表示
print(freq_str)
2m

この方法は、推定頻度だけでなく、最小公倍数である正確な頻度を取得することができます。

pd.Series と to_timedelta() メソッドを使用する

pd.Seriesto_timedelta() メソッドを使用して、TimedeltaIndex オブジェクトを作成し、その頻度を取得することができます。

import pandas as pd

# ランダムな時間差のリスト
time_diffs = [pd.Timedelta('10 seconds'), pd.Timedelta('2 minutes'), pd.Timedelta('3 hours')]

# Series に変換
s = pd.Series(time_diffs)

# TimedeltaIndex に変換
tdidx = s.to_timedelta()

# 頻度を取得
freq = tdidx.inferred_freq

# 頻度を文字列に変換
freq_str = str(freq).lower() + (freq.unit if freq.unit else '')

# 推定頻度を表示
print(freq_str)

この方法は、TimedeltaIndex オブジェクトを作成してから inferred_freq 属性を使用するため、to_freq() メソッドと同様に、推定ではなく設定した値に基づいた正確な頻度を取得することができます。

pandas.TimedeltaIndex.inferred_freq は推定値であるため、より正確な頻度を取得したい場合は、to_freq() メソッド、df.diff() メソッドと df.dropna() メソッド、pd.Seriesto_timedelta() メソッドなどの代替方法を検討することをおすすめします。