今回は、Pandasを使った日付の条件抽出の練習です。
【実行環境】
目次
データフレームを日付で条件抽出
日付による条件抽出をやってみる。
◇ 連続日付データの生成
import pandas as pd import numpy as np # データフレーム生成 df=pd.DataFrame({ '日付':pd.date_range(start="2021/1/1",freq="d",periods=20), '何かの値':np.random.randint(1,51,20), 'アイテム':np.random.choice(['砂糖','醤油','酢','みりん','塩','ごま油','鰹だし','昆布だし','アゴだし','味噌'], 20) }) df
日付 | 何かの値 | アイテム | |
---|---|---|---|
0 | 2021-01-01 | 6 | 砂糖 |
1 | 2021-01-02 | 41 | ごま油 |
2 | 2021-01-03 | 25 | 塩 |
3 | 2021-01-04 | 36 | ごま油 |
4 | 2021-01-05 | 26 | ごま油 |
5 | 2021-01-06 | 13 | ごま油 |
6 | 2021-01-07 | 13 | 酢 |
7 | 2021-01-08 | 16 | 昆布だし |
8 | 2021-01-09 | 13 | 塩 |
9 | 2021-01-10 | 45 | 塩 |
10 | 2021-01-11 | 32 | アゴだし |
11 | 2021-01-12 | 15 | 塩 |
12 | 2021-01-13 | 17 | ごま油 |
13 | 2021-01-14 | 4 | 鰹だし |
14 | 2021-01-15 | 12 | 砂糖 |
15 | 2021-01-16 | 11 | アゴだし |
16 | 2021-01-17 | 25 | 昆布だし |
17 | 2021-01-18 | 31 | 砂糖 |
18 | 2021-01-19 | 29 | 塩 |
19 | 2021-01-20 | 35 | 昆布だし |
query()の条件抽出の練習
df.query()
を使って条件抽出する場合、
- 引数の中身全体 : シングルクォーテーション「
'
」で括ります。 - データの値 : str型の値はダブルクォーテーション「
"
」で括る。 - データの値 : 数値型はクォーテーシふョンを付けない。
- カラム名やインデックス名 : クォーテーションは付けず、そのまま
例1)
↑のデータの、「アイテム列がアゴだしを抽出」の場合、query()の引数は
'アイテム == "アゴだし"'
にする。
やってみましょ。
# アイテム列が「アゴだし」のデータを抽出 df.query('アイテム == "アゴだし"')
例2)
「何かの値」列が15以上25未満のデータを抽出。
# 何かの値列が15以上25未満のデータを抽出 df.query('15 <= 何かの値 < 25')
日付 | 何かの値 | アイテム | |
---|---|---|---|
7 | 2021-01-08 | 16 | 昆布だし |
11 | 2021-01-12 | 15 | 塩 |
12 | 2021-01-13 | 17 | ごま油 |
例3)
何かの値列が30以上で、かつ、アイテムが塩ではないデータを抽出。
# 何かの値が30以上で、かつアイテムが塩ではないデータ df.query('30 <= 何かの値 and アイテム != "塩"')
日付 | 何かの値 | アイテム | |
---|---|---|---|
1 | 2021-01-02 | 41 | ごま油 |
3 | 2021-01-04 | 36 | ごま油 |
10 | 2021-01-11 | 32 | アゴだし |
17 | 2021-01-18 | 31 | 砂糖 |
19 | 2021-01-20 | 35 | 昆布だし |
例4)
何かの値が10未満、もしくは40より大きいデータを抽出。
# 何かの値が10未満、もしくは40より大きいデータを抽出 df.query('何かの値 < 10 or 40 <= 何かの値')
日付 | 何かの値 | アイテム | |
---|---|---|---|
0 | 2021-01-01 | 6 | 砂糖 |
1 | 2021-01-02 | 41 | ごま油 |
9 | 2021-01-10 | 45 | 塩 |
13 | 2021-01-14 | 4 | 鰹だし |
練習はこのへんにして、日付データの抽出に進みます。
df.query()で日付から条件抽出
数値型はダブルクォーテーションを付けませんでしたが、日付型はダブルクォーテーションが必要です。付けないとエラーが出る。
日付が1/5よりあとで、1/8より前のデータを抽出。
# 日付で条件抽出 df.query('"2021-01-05" < 日付 < "2021-01-08"')
日付 | 何かの値 | アイテム | |
---|---|---|---|
5 | 2021-01-06 | 13 | ごま油 |
6 | 2021-01-07 | 13 | 酢 |
日付プラス他で条件抽出
and(かつ)で条件を組み合わせて抽出。
日付が1/1以降で1/8より前、かつ何かの値が3以上15未満のデータを抽出。
# 日付と他の列のデータから条件抽出 df.query('"2021-01-01" <= 日付 < "2021-01-08" and 3 <= 何かの値 < 15')
日付 | 何かの値 | アイテム | |
---|---|---|---|
0 | 2021-01-01 | 6 | 砂糖 |
5 | 2021-01-06 | 13 | ごま油 |
6 | 2021-01-07 | 13 | 酢 |
1/1と1/6と1/7の3つが抽出された。本当に合ってるのか、条件を個別に確認します。
# 日付の条件 left = df.query('"2021/1/1" <= 日付 < "2021/1/8"') left
日付 | 何かの値 | アイテム | |
---|---|---|---|
0 | 2021-01-01 | 6 | 砂糖 |
1 | 2021-01-02 | 41 | ごま油 |
2 | 2021-01-03 | 25 | 塩 |
3 | 2021-01-04 | 36 | ごま油 |
4 | 2021-01-05 | 26 | ごま油 |
5 | 2021-01-06 | 13 | ごま油 |
6 | 2021-01-07 | 13 | 酢 |
日付の書き方は2021-01-01
じゃなく2021/1/1
でもエラーなく実行できた。
# 何かの値が3以上15未満 right = df.query('3 <= 何かの値 < 15') right
日付 | 何かの値 | アイテム | |
---|---|---|---|
0 | 2021-01-01 | 6 | 砂糖 |
5 | 2021-01-06 | 13 | ごま油 |
6 | 2021-01-07 | 13 | 酢 |
8 | 2021-01-09 | 13 | 塩 |
13 | 2021-01-14 | 4 | 鰹だし |
14 | 2021-01-15 | 12 | 砂糖 |
15 | 2021-01-16 | 11 | アゴだし |
無駄にleft
やright
と変数に代入させたのは、データフレームの結合の練習の為w
inner結合すれば、2つの条件に合うデータだけが残るだろう!! ( ・`д・´)
# 条件抽出した2つをinner結合 pd.merge(left, right, on="日付", how="inner")
日付 | 何かの値_x | アイテム_x | 何かの値_y | アイテム_y | |
---|---|---|---|---|---|
0 | 2021-01-01 | 6 | 砂糖 | 6 | 砂糖 |
1 | 2021-01-06 | 13 | ごま油 | 13 | ごま油 |
2 | 2021-01-07 | 13 | 酢 | 13 | 酢 |
3つが残った。合ってるということで。
df.query()を使わず日付で条件抽出
クォーテーションはシングルでもダブルでもよし。
日付の書き方も以下の通り自由度が高い。
# 日付で条件抽出 df[df['日付'] > '2021/1/15'] #df[df['日付'] > '2021-1-15'] #でも同じ#df[df['日付'] > "1/15/2021"] #でも同じ
日付 | 何かの値 | アイテム | |
---|---|---|---|
15 | 2021-01-16 | 11 | アゴだし |
16 | 2021-01-17 | 25 | 昆布だし |
17 | 2021-01-18 | 31 | 砂糖 |
18 | 2021-01-19 | 29 | 塩 |
19 | 2021-01-20 | 35 | 昆布だし |
日付列がインデックスの時の条件抽出
日付列をインデックスに変更して行ってみる。
# 日付列をインデックスに変更 dti = df.set_index('日付') dti.head(3)
何かの値 | アイテム | |
---|---|---|
日付 | ||
2021-01-01 | 6 | 砂糖 |
2021-01-02 | 41 | ごま油 |
2021-01-03 | 25 | 塩 |
# 日付による条件抽出 (月、日、年の順序でもできる) dti[dti.index < '1/7/2021']
何かの値 | アイテム | |
---|---|---|
日付 | ||
2021-01-01 | 6 | 砂糖 |
2021-01-02 | 41 | ごま油 |
2021-01-03 | 25 | 塩 |
2021-01-04 | 36 | ごま油 |
2021-01-05 | 26 | ごま油 |
2021-01-06 | 13 | ごま油 |
日付列をインデックスに変更しているので、条件もインデックスに対して行う。
一定期間ごとの集計
年ごと、月ごと、週ごと、四半期ごとなど、一定期間の集計を行いたい場合、条件抽出をしてからsum()
やmean()
で集計するという手間を掛けずに、df.resample()
を使った以下のような方法で簡単に出来ます。
注意として、このとき使用するデータフレームは日付列がインデックスになっている必要があります。
# 使用するデータフレーム 上の三行を表示 dti.head(3)
何かの値 | アイテム | |
---|---|---|
日付 | ||
2021-01-01 | 6 | 砂糖 |
2021-01-02 | 41 | ごま油 |
2021-01-03 | 25 | 塩 |
# 5日ごとの集計、平均 dti.resample('5d').mean()
何かの値 | |
---|---|
日付 | |
2021-01-01 | 26.8 |
2021-01-06 | 20.0 |
2021-01-11 | 16.0 |
2021-01-16 | 26.2 |
# 週ごとの集計、合計 dti.resample('w').sum()
何かの値 | |
---|---|
日付 | |
2021-01-03 | 72 |
2021-01-10 | 162 |
2021-01-17 | 116 |
2021-01-24 | 95 |
resample()
の使い方はこちらを参考ください。
【Pandas resample()】月別集計、時系列データを期間ごとに集計する方法 - よちよちpython
おわりに
条件抽出はデータ分析100本ノックなどに正規表現を混ぜたり高度な方法を知らないと出来ないようなものが載っていたので、勉強が進んでからでも詳しくやろうかと思います。
以上です。