時系列データを扱っていると、過去実績を追加したいことがある。
過去7日間の平均を求める移動平均等は調べればいくらでも出てきますが、
”過去の同週同曜日を追加する”はあまり見かけませんでした。
早速やり方メモを紹介します。
◆手順
- 日付データから週番号を付与
- 日付データから曜日番号を付与
- 過去の年の週番号、曜日番号が一致ものが過去の同週同曜日
from datetime import datetime
import pandas as pd
# 過去の実績を格納するリスト
y_last = []
# 日付データ、実績データを含むDataFrameの読込み
# 'datetime'は日付データ、'y'は実績データ
df = pd.read_csv('...')# 何年前の実績と比較するか。去年であれば1
past=1
# 日付一つ一つfor文を回す
for dt in df['datetime'].unique():
# isocalendar()はタプルで(yyyy、週番号、曜日番号)を返す
# ここではタプルは使いにくいのでリストに変換
temp=list(pd.to_datetime(dt).isocalendar())
# 曜日番号については注意1参照
# ここでは日曜日=0になるように修正
if temp[2]==7:
temp[2]=0
# うるう年があると週番号が1週ずれる可能性があり、補正
if (temp[0] >= 2014) & (temp[0] < 2017):
temp[1]=temp[1]-1
# 他のデータとの兼合いで'yyyy-週番号-曜日番号'の文字列に変換。
# このときtemp[0]は過去の参照したい年に合わせて引き算しておく。
t=str(temp[0]-past)+'-'+str(temp[1])+'-'+str(temp[2])
# 年、週番号、曜日番号から日付を逆算
t_=datetime.strptime(t, "%Y-%W-%w") # 年、週番号、曜日番号
# dfにおいて、t_と一致する行の実績データyを抽出する
val=df[df['datetime']==t_.strftime('%Y-%m-%d')]['y'].values
# もし過去実績データvalに値がなければNaN(欠損)として扱う
if len(val)==0:
val=np.nan
else:
val=val[0]
# 最後に、値を格納していく
y_last.append(val)
# 最後に適当にdfに過去実績をカラムとして作成
df['last_y']=y_last
注意1 曜日番号について
曜日番号は使う関数によって定義が異なるので突合する際は変換が必要。(とても面倒くさい)
- isocalendar()
定義: 月1、火2、水3、木4、金5、土6、日7 - datetime.strptime
定義: 月1、火2、水3、木4、金5、土6、日0 - weekday()
定義: 月0、火1、水2、木3、金4、土5、日6
同週同曜日の情報をもっとストレートに求められると嬉しいです。
結構、時系列データを扱う上では必須の機能ですよね…
コメント