DataFrameの日付の欠損行を埋める方法

日付に限らず連番等でも使える方法ですが、自分が日単位の時系列データで行うことが多いのでそれで説明します。

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に慣れてない場合は別の方法でも大丈夫です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です