結論
作成したDataFrameの日付のフォーマットや型に問題がある!
→ 日付のフォーマットは、1/1は01/01の様に記述するなど統一されているか?
→ 日付のデータの型は、to_datetime関数を使うなどして日付の型になっているか?
DataFrameを作成し、groupbyのsumで日付別の合計値を求める。(ダメな例)
下記の様な日付ごとに果物をいくつ買ったかというDataFrameがあるとする。
import pandas as pd
df = pd.DataFrame({'Date': ['2022/9/1', '2022/9/1', '2022/9/12', '2022/9/12','2022/10/20', '2022/10/20', '2022/11/27', '2022/12/31'],
'Fruit': ['Apple', 'Banana', 'Apple', 'Orange', 'Grape', 'Apple', 'Grape', 'Orange'],
'Sale': [3, 1, 2, 7, 3, 1, 8, 4]})
実際のDataFrameは以下の様な感じ。
| Date | Fruit | Sale | |
|---|---|---|---|
| 0 | 2022/9/1 | Apple | 3 |
| 1 | 2022/9/1 | Banana | 1 |
| 2 | 2022/9/12 | Apple | 2 |
| 3 | 2022/9/12 | Orange | 7 |
| 4 | 2022/10/20 | Grape | 3 |
| 5 | 2022/10/20 | Apple | 1 |
| 6 | 2022/11/27 | Grape | 8 |
| 7 | 2022/12/31 | Orange | 4 |
このDataFrameから、日付別で果物合計いくつ購入したかを以下の様なコードで算出。
df.groupby(by=['Date']).sum()
しかし、結果としてDateの順序がおかしくなる。
| Date | Sale |
|---|---|
| 2022/10/20 | 4 |
| 2022/11/27 | 8 |
| 2022/12/31 | 4 |
| 2022/9/1 | 4 |
| 2022/9/12 | 9 |
本来やりたいのはこっち⇩
| Date | Sale |
|---|---|
| 2022/9/1 | 4 |
| 2022/9/12 | 9 |
| 2022/10/20 | 4 |
| 2022/11/27 | 8 |
| 2022/12/31 | 4 |
何故こうなってしまうのか?
原因: Dateがstr型として扱われている。
以下のようにDate列の各々の要素がstr型であるので、groupbyメソッドをDateに対して使用した結果、str型の順にsortされるといった現象が起こっている。
type(df.iat[0,0])
>>> str
これにより2022/9/1と2022/9/12のsort順がおかしくなる現象が発生している。
解決法①: Date列にto_datetime関数を利用し、str型から日付データに変換する。
DataFrameのDate列に対し、以下のコードを実行する事で、str型からTimestamp型に変更できる。
df["Date"] = pd.to_datetime(df["Date"])
上記コードを実行した後groupbyすれば、以下の様なDataFrameが作成される。
| Date | Sale |
|---|---|
| 2022-09-01 | 4 |
| 202209-12 | 9 |
| 2022-10-20 | 4 |
| 2022-11-27 | 8 |
| 2022-12-31 | 4 |
こちらの方法だと、型を変更する事で日付のフォーマットを統一することができる。
解決法②: groupbyメソッドを使用した際に、sortせずに元の順序を維持する。
何らかの事情で、元のフォーマットや型をいじりたくない人には、こちらを使って欲しい。
元の順序を維持するには、.groupby(..., sort=False)とする事で解決する。
df.groupby(by=['Date'], sort=False).sum()
結果、以下の様なDataFrameが作成される。
| Date | Sale |
|---|---|
| 2022/9/1 | 4 |
| 2022/9/12 | 9 |
| 2022/10/20 | 4 |
| 2022/11/27 | 8 |
| 2022/12/31 | 4 |
ニッチな領域だと思うが、誰かの役に立てれば幸いである。