PythonのDataFrameで日付を取り扱う
pandasで時系列データを取り扱った際の気付き諸々をまとめていく。(随時更新予定)
1. pandas DataFrameで日付データをDatetime indexとして取り扱う
日付ベースのデータをもとに集計する場合は、日付データをDatetime indexとして取り扱った方が何かと便利と思われる。
1.1. 利点 Group_byによる集計が簡単
たとえば月次/四半期での集計は pd.Grouper(freq='param')
を用いて実施できる。
import pandas as pd
import numpy as np
from datetime import date
# `pd.date_range`で2022年1年分の日付を作成。
pd_dates = pd.date_range(start='2022-01-01', end='2022-12-31')
np.random.seed(100)
df_pd = pd.DataFrame(
np.random.randint(1, 100, len(pd_dates)), index=pd_dates, columns=['count']
)
# 月次集計
monthly_mean = df_pd.groupby(pd.Grouper(freq='M')).mean()
# 四半期集計
quarterly_mean = df_pd.groupby(pd.Grouper(freq='Q')).mean()
上記コードの出力例:
# monthly_mean=月次集計の出力
| | count |
| ---------- | --------- |
| 2022-01-31 | 44.806452 |
| 2022-02-28 | 51.214286 |
| 2022-03-31 | 50.225806 |
| 2022-04-30 | 53.100000 |
| 2022-05-31 | 48.419355 |
| 2022-06-30 | 52.133333 |
| 2022-07-31 | 48.322581 |
| 2022-08-31 | 54.774194 |
| 2022-09-30 | 52.000000 |
| 2022-10-31 | 47.096774 |
| 2022-11-30 | 49.800000 |
| 2022-12-31 | 50.322581 |
quarterly_mean=四半期集計の出力。
| | count |
| ---------- | --------- |
| 2022-03-31 | 48.666667 |
| 2022-06-30 | 51.186813 |
| 2022-09-30 | 51.695652 |
| 2022-12-31 | 49.065217 |
ちなみに、 resample
でもおなじ集計が可能。
1.2. チョット欠点
上記の出力を見て解るように、集計後のDatetimeIndexはグループの「末日」が表記される。
「末尾まで集計した」と理解すれば解りやすいとも言えるが直感的ではない。
1.3. 改善案
これでは、意味が捉えにくいこともあるので、 pd.PeriodIndex
と strftime
を用いてpd.indexを月次or四半期の表記に変更する。
グラフ化やテーブル出力する際にはこの形でHuman Readableにしておくほうがよい。
monthly_mean.index = pd.PeriodIndex(monthly_mean.index).strftime('%Y-%m')
quarterly_mean.index = pd.PeriodIndex(quarterly_mean.index).strftime('%Y-Q%q')
| | count|
| ---- | --- |
| 2022-01 | 44.806452 |
| 2022-02 | 51.214286 |
| 2022-03 | 50.225806 |
| 2022-04 | 53.100000 |
| 2022-05 | 48.419355 |
| 2022-06 | 52.133333 |
| 2022-07 | 48.322581 |
| 2022-08 | 54.774194 |
| 2022-09 | 52.000000 |
| 2022-10 | 47.096774 |
| 2022-11 | 49.800000 |
| 2022-12 | 50.322581 |
| | count|
| ---- | --- |
| 2022-Q1 | 48.666667 |
| 2022-Q2 | 51.186813 |
| 2022-Q3 | 51.695652 |
| 2022-Q4 | 49.065217 |
2. PeriodIndexの応用:会計年度(fiscal year)と四半期を表示する方法
日本企業だけでなく、会社のデータを集計する場合は何かと「会計年度」「決算年度」「四半期」での集計がもとめられる。
PeriodIndex
の freq
オプションを使うと日付を「年度」に変更できる。
上記とは少々違う事例で試してみる。
df = pd.DataFrame({
'date': ['2022-01-01', '2023-04-01', '2024-07-01', '2025-12-01']
})
df['date'] = pd.to_datetime(df['date'])
- 3月を期末として年度を取得する方法:
freq
にA-MAR
を設定して1を引く(理由は後述) - 3月を期末として設定した年度の四半期を取得する方法:
freq
にQ-MAR
を設定する
具体的なコードと出力:
df['fiscal_year'] = (pd.PeriodIndex(df['date'], freq='A-MAR') - 1).strftime('FY%Y')
df['fy_quarter'] = (pd.PeriodIndex(df['date'], freq='Q-MAR')).strftime('Q%q')
print(df)
# 上記コードの出力
date fiscal_year fy_quarter
0 2022-01-01 FY2021 Q4
1 2023-04-01 FY2023 Q1
2 2024-07-01 FY2024 Q2
3 2025-12-01 FY2025 Q3
1を除算する理由
pd.PeriodIndex(df['date'], freq='A-MAR')
の出力は以下となる。
# 上記コードの出力
PeriodIndex(['2022', '2024', '2025', '2026'], dtype='period[A-MAR]', name='date')
df['date']
は ['2022-01-01', '2023-04-01', '2024-07-01', '2025-12-01']
である。
これを処理した際の期待する出力は ['2021', '2023', '2024', '2023']
だが、実際には ['2022', '2024', '2025', '2026']
が出力される。
これは、PeriodIndexの処理 [1] がMARを最終月とした年次、すなわち4月に次の年次が開始する処理をしているしているためである。
期待する「年度」を出力するためには、1を除算して解決する。
3. 参考としたサイト
-
PeriodIndexはarray-likeデータを引数にとって
PeriodIndex
オブジェクトを返す。 ↩︎
Discussion