日付に限らず連番等でも使える方法ですが、自分が日単位の時系列データで行うことが多いのでそれで説明します。
DBなどからデータを日単位で集計してpandasのDataFrameを作った時、集計対象のデータがなかった日は行ごと欠損してしまった状態になります。
例えば次のような感じです。
print(df.head(5))
"""
date value
0 2020-01-02 9
1 2020-01-06 3
2 2020-01-07 4
3 2020-01-09 9
4 2020-01-11 2
"""
print(df.tail(5))
"""
date value
15 2020-02-01 3
16 2020-02-02 2
17 2020-02-09 3
18 2020-02-11 2
19 2020-02-18 2
"""
このままで困らないこともあるのですが、累積和をとるときや、matplotlibで可視化するときなど、
欠損してる日付を補完しておきたいことがあります。
これまで、補完対象のDataFrameを別途構成してappendすることが多かったのですが、
必要な日付の一覧を持ったDataFrameと結合(SQLでいうJoin,pandasの関数ではMerge)すると手軽に補完できることに気づきました。
具体的には次のようなコードになります。
# dates に必要な期間の日付の一覧が入ってるとします。
date_df = pd.DataFrame({"date": dates})
# date_df と 結合する
df = pd.merge(date_df, df, on="date", how="left")
# NaNを 0で埋める
df[["value"]] = df[["value"]].fillna(0)
この例だと単純なので、不足している分のデータFrameを作ってたすのと比べて、あまりメリットを感じないのですが、
これが、例えば複数のキーに対してそれぞれ日付データを全部揃えたいケースになると、かなり楽になります。
例えば、元のデータフレームが次だったとします。
print(df2)
"""
key date value
0 key1 2020-01-03 5
1 key1 2020-01-04 3
2 key1 2020-01-10 5
3 key2 2020-01-02 4
4 key2 2020-01-03 1
5 key2 2020-01-04 9
6 key3 2020-01-04 2
7 key3 2020-01-06 5
8 key3 2020-01-09 8
"""
このDataFrameの key1,key2,key3 に対して、 2020-01-01〜2020-01-10の行を全て揃えたいとします。
このようなときは、次鵜のようにして、keyの値と日付の値のペア全てのDataFrameを作ってそれと結合すると簡単に保管できます。
# key と 日付のペアを網羅したDataFrameを作る
keys, dates = np.meshgrid(
["key1", "key2", "key3"],
[(datetime(2020, 1, 1) + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(10)]
)
key_date_df = pd.DataFrame(
{
"key": keys.ravel(),
"date": dates.ravel(),
}
)
# 結合してソート
df2 = pd.merge(key_date_df, df2, how="left").sort_values(["key", "date"])
# NaNを 0で埋める
df2[["value"]] = df2[["value"]].fillna(0)
# インデックのリセット
df2.reset_index(inplace=True, drop=True)
途中で meshgridを使いましたが、meshgridに慣れてない場合は別の方法でも大丈夫です。