実現したい
日付 | ID | 付番 | カウント率 |
---|---|---|---|
… | … | … | |
2021-12-31 | 14 | 1 | |
2022-01-01 | 10 | 3 | |
2022-01-01 | 11 | 2 | |
2022-01-01 | 12 | 2 | |
2022-01-02 | 15 | 3 | |
2022-01-02 | 12 | 2 | |
2022-01-02 | 18 | 1 | |
2022-01-03 | 11 | 1 | |
… | … | … | |
2022-12-31 | 11 | 3 |
上記のようなデータフレームにおいて、各行の"カウント率"列に下記④の値を入力したいです。
①各行の日付の前日を基準日として、その180日以内の日付が含まれる行をデータフレームから抽出し、
②上記①で抽出した行のうち、IDが一致する行を抽出したときの行数をAとし、
③上記②で抽出した行のうち、付番が1または2である行を抽出したときの行数をBとしたときの、
④B/A×100の値
(上記データフレームの一番下の行を例にすると、2022.6.30~2022.12.30の間で、IDが11である行数をAとし、Aのなかで付番が1または2である行数をBとし、B/A×100の値を"カウント率"列に入力したいです)
前提
jupyter labを使用してpythonでのデータ集計を行おうとしています。
自身で下記コードを書いたのですが、実際はデータフレームの行数が200万近くあり、処理時間がとても長く実用に耐えませんでした。
初歩的な質問で恐縮ですが、高速化を図れる術をご教示いただきたいです。宜しくお願いいたします。
発生している問題・エラーメッセージ
エラーメッセージ
該当のソースコード
python
1def sample(row): 2 all = len(df[(row["日付"] >df["日付"])& 3 (df["日付"]> row["日付"] - timedelta(days=180))& 4 (df["ID"] == row["ID"]) 5 ] ) 6 count = len(df[((row["日付"] > df["日付"])& 7 (df["日付"]> row["日付"] - timedelta(days=180))& 8 (df["ID"] == row["ID"]))& 9 (df["付番"].isin([1,2])) 10 ] ) 11 try: 12 count_rate = count/all * 100 13 except ZeroDivisionError: 14 count_rate = np.nan 15 row["カウント率"] = count_rate 16 return row 17 18df_new = df.apply(sample,axis=1)
試したこと
swifterを使用しましたが処理時間がほとんど変わらず、またnp.vectorizeを試みたのですが知識不足により実装することができませんでした。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答3件
あなたの回答
tips
プレビュー