pandasの日付データを週単位で丸める(to_periodを使う方法)

前回の記事では、トレジャーデータで週単位の集計をする方法を紹介しましたが、今回はすでにDBから抽出が終わっているデータを週単位で集計する方法を紹介します。

日時の列をindexに設定してresampleするとか、方法はいろいろあるのですが、週単位の集計の場合、個人的にはto_period メソッドを使って丸めるのが一番気に入っているのでそれを紹介します。

ドキュメントはこちらです。
参考: pandas.Series.dt.to_period — pandas 1.3.2 documentation

とりあえずデータを作っておきます。

import pandas as pd


df = pd.DataFrame({
    'date': [
        '2021-08-01',
        '2021-08-02',
        '2021-08-03',
        '2021-08-04',
        '2021-08-05',
        '2021-08-06',
        '2021-08-07',
        '2021-08-08',
        '2021-08-09',
        '2021-08-10',
    ]
})
print(df)
"""
         date
0  2021-08-01
1  2021-08-02
2  2021-08-03
3  2021-08-04
4  2021-08-05
5  2021-08-06
6  2021-08-07
7  2021-08-08
8  2021-08-09
9  2021-08-10
"""

to_period メソッドは、 datetime系の型の列でなければ使えないので、pd.to_datetime() して型を変換します。

df["date"] = pd.to_datetime(df["date"])

さて、これで準備が整いました。1週間単位で日付を丸めたい場合は、最初の引数(freq)に”W”を指定して to_period メソッドを使えばOKです。

print(df["date"].dt.to_period("W"))
"""
0    2021-07-26/2021-08-01
1    2021-08-02/2021-08-08
2    2021-08-02/2021-08-08
3    2021-08-02/2021-08-08
4    2021-08-02/2021-08-08
5    2021-08-02/2021-08-08
6    2021-08-02/2021-08-08
7    2021-08-02/2021-08-08
8    2021-08-09/2021-08-15
9    2021-08-09/2021-08-15
Name: date, dtype: period[W-SUN]
"""

2021-08-01 は、 2021-07-26(月)〜2021-08-01(日)の週に丸められ、
2021-08-02〜2021-08-08は、2021-08-02(月)〜2021-08-08(日)の週に丸められましたね。
ちなみにこの結果は、Periodというデータ型になっています。
元と同じようにdatetime型で扱いたい場合や、丸めた週の頭の日付にしたいという場合はさらに変換する必要があります。自分はもっぱら次の形で使うことが多いです。

df["week"] = df["date"].dt.to_period("W").dt.to_timestamp()
print(df)
"""
        date       week
0 2021-08-01 2021-07-26
1 2021-08-02 2021-08-02
2 2021-08-03 2021-08-02
3 2021-08-04 2021-08-02
4 2021-08-05 2021-08-02
5 2021-08-06 2021-08-02
6 2021-08-07 2021-08-02
7 2021-08-08 2021-08-02
8 2021-08-09 2021-08-09
9 2021-08-10 2021-08-09
"""

あとは、この週単位に変換した列を使って groupbyして、sumなりcountなり望みの集計をすることで、Pandasのデータを週単位で集計することができます。

週単位以外の基準で集計したい場合、”W”以外の対応した文字を使えば実現可能です。
例えば月単位なら”M”、日単位なら”D”などです。
利用可能な集計基準と対応する文字は、こちらのページにまとまっています。
参考: Offset aliases

ただ、TD_TIME_TRUNCの記事でも似たような話を書きましたが、日単位や月単位で集計したいのであれば、to_periodして、timestumpに戻して、とやるよりも、strftimeなどを使った方が簡単だと思います。例えば月単位で集計したいなら次のように変換できます。

print(df["date"].dt.strftime("%Y-%m-01"))
"""
0    2021-08-01
1    2021-08-01
2    2021-08-01
3    2021-08-01
4    2021-08-01
5    2021-08-01
6    2021-08-01
7    2021-08-01
8    2021-08-01
9    2021-08-01
Name: date, dtype: object
"""

日単位の場合は、 “%Y-%m-%d”です。

ドキュメントになぜか記載がないのですが、週単位で丸める場合、週の始まりの曜日(実際にコードで指定するのは週の終わりの曜日)を指定することもできます。
方法は簡単で、”W”の代わりに、”W-WED”(水曜日終わり、木曜日始まり)、や、
“W-FRI”(金曜日終わり、土曜日始まり)などを指定します。
“W”は”W-SUN”(日曜日終わり、月曜日始まり)と同じ挙動になります。
基本的に”W”を使っていれば良いと思うのですが、開始日を変えたいこともあると思いますので覚えておくと役に立つ場面もあるかもしれません。

コメントを残す

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