Python Pandas:统计值变更前前置符合条件行数(向量化实现)
需求说明
我有如下DataFrame,需要生成Days_Out列:
| Name_ID | Date | Out_In | Change | Form_Req | Days_Out |
|---|---|---|---|---|---|
| 1001 | 01/01/2022 | 0 | 0 | 0 | 0 |
| 1001 | 02/01/2022 | 1 | 1 | 0 | 0 |
| 1001 | 03/01/2022 | 1 | 0 | 0 | 0 |
| 1001 | 04/01/2022 | 1 | 0 | 0 | 0 |
| 1001 | 05/01/2022 | 0 | 1 | 1 | 3 |
| 1001 | 06/01/2022 | 0 | 0 | 0 | 0 |
| 1001 | 07/01/2022 | 1 | 1 | 0 | 0 |
| 1001 | 08/01/2022 | 0 | 1 | 1 | 1 |
规则:每当Form_Req列值为1时,统计该位置之前连续出现的Out_In列中值为1的行数(直到遇到0为止)。由于数据量超过100万行,必须采用向量化解决方案,避免循环导致性能问题。
向量化解决方案
以下是基于pandas的高效实现,全程无循环,适配百万级数据量:
import pandas as pd # 假设你的数据存储在df中,若Date列未转为日期类型可执行下方注释代码 # df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y') # 1. 标记连续Out_In=1的分组 # 当当前行Out_In=1且上一行是0时,触发新分组 df['group_id'] = (df['Out_In'] == 1) & (df['Out_In'].shift(1) == 0) df['group_id'] = df['group_id'].cumsum() # 2. 每个分组内累计计数连续1的行数 df['running_count'] = df.groupby('group_id')['Out_In'].cumsum() # 3. 为Form_Req=1的行赋值对应连续1的行数,其余行设为0 df['Days_Out'] = df['running_count'].shift(1).where(df['Form_Req'] == 1, 0) # 可选:清理临时辅助列 df = df.drop(['group_id', 'running_count'], axis=1)
逻辑说明
- 分组标识:
group_id用于区分每一段连续的Out_In=1序列,确保每一段独立计数。 - 累计计数:在每个分组内对
Out_In求和(因Out_In是0/1,求和等价于计数),得到该段连续1的累计行数。 - 赋值逻辑:当
Form_Req=1时,取上一行的累计计数(即该段连续1的总长度),其他位置设为0,完全匹配需求。
内容的提问来源于stack exchange,提问作者Declan Mc Gann
相关产品推荐
相关产品推荐

