pandasのreindexとdate_rangeを利用して、時系列データの欠損を埋める
ECサイトの売上のデータ解析などをしていると、休日のデータが欠損している場合がある。 解析時には日付が欠損していると不便なことがあるので、0などのある値で埋めるために、pandasのreindexとdate_rangeを利用する。
github
- githubのjupyter notebook形式のファイルはこちら
google colaboratory
- google colaboratory で実行する場合はこちら
実行環境
!sw_vers
ProductName: macOS
ProductVersion: 11.6.7
BuildVersion: 20G630
!python -V
Python 3.8.13
時系列データでデータの穴抜けがあるDataFrameを用意する。
import pandas as pd
df = pd.DataFrame({
'sales': [i + 1 for i in range(5)],
'date': pd.to_datetime(['2022-07-01', '2022-07-02', '2022-07-05', '2022-07-06', '2022-07-09'])
})
df
sales | date | |
---|---|---|
0 | 1 | 2022-07-01 |
1 | 2 | 2022-07-02 |
2 | 3 | 2022-07-05 |
3 | 4 | 2022-07-06 |
4 | 5 | 2022-07-09 |
土日が休みや定休日があるお店だとよく見られるデータである。
時系列データで日付に穴があると、解析時に不便な場合があるので、これを埋める事が今回の目的である。
date_range
pandasにはdate_rangeという連続的な日次のデータを作成してくれる関数がある。
startとendを設定し、frequencyを指定するだけである。
freqに60min
を設定すると1時間毎に、240min
を指定すると4時間毎のdatetime型のlistを作ることができる。
pd.date_range('2022-07-01', '2022-07-02', freq='60min')
DatetimeIndex(['2022-07-01 00:00:00', '2022-07-01 01:00:00',
'2022-07-01 02:00:00', '2022-07-01 03:00:00',
'2022-07-01 04:00:00', '2022-07-01 05:00:00',
'2022-07-01 06:00:00', '2022-07-01 07:00:00',
'2022-07-01 08:00:00', '2022-07-01 09:00:00',
'2022-07-01 10:00:00', '2022-07-01 11:00:00',
'2022-07-01 12:00:00', '2022-07-01 13:00:00',
'2022-07-01 14:00:00', '2022-07-01 15:00:00',
'2022-07-01 16:00:00', '2022-07-01 17:00:00',
'2022-07-01 18:00:00', '2022-07-01 19:00:00',
'2022-07-01 20:00:00', '2022-07-01 21:00:00',
'2022-07-01 22:00:00', '2022-07-01 23:00:00',
'2022-07-02 00:00:00'],
dtype='datetime64[ns]', freq='60T')
pd.date_range('2022-07-01', '2022-07-02', freq='240min')
DatetimeIndex(['2022-07-01 00:00:00', '2022-07-01 04:00:00',
'2022-07-01 08:00:00', '2022-07-01 12:00:00',
'2022-07-01 16:00:00', '2022-07-01 20:00:00',
'2022-07-02 00:00:00'],
dtype='datetime64[ns]', freq='240T')
reindex
date_rangeとreindexを利用して、欠損データの穴埋めをする。
reindexは設定されいるindexに値があるときはその値が割り振られ、値がない場合はNaNが割り振られる。
ただ、穴埋めするデータもfill_value
で指定することができる。今回は0で埋める。
start_time = df['date'].tolist()[0]
end_time = df['date'].tolist()[-1]
time_list = pd.date_range(start_time, end_time, freq='1d')
df.set_index('date').reindex(time_list, fill_value=0)
sales | |
---|---|
2022-07-01 | 1 |
2022-07-02 | 2 |
2022-07-03 | 0 |
2022-07-04 | 0 |
2022-07-05 | 3 |
2022-07-06 | 4 |
2022-07-07 | 0 |
2022-07-08 | 0 |
2022-07-09 | 5 |
7/3や7/4などの欠損データが0で穴埋めされている。
意味がないが、reindexの引数のlistに応じてデータを並び替えることができるので、time_list[::-1]
とすると、順序を逆にすることができる。
df.set_index('date').reindex(time_list[::-1], fill_value=0)
sales | |
---|---|
2022-07-09 | 5 |
2022-07-08 | 0 |
2022-07-07 | 0 |
2022-07-06 | 4 |
2022-07-05 | 3 |
2022-07-04 | 0 |
2022-07-03 | 0 |
2022-07-02 | 2 |
2022-07-01 | 1 |
date_rangeもreindexも使用頻度は高くないので、忘れないようにする。