按条件递增行值并按组保留最新值的实现需求
按分组生成递增/继承的new_val字段问题
需求:
- 按
no字段分组,每组首行的new_val设为1 - 当
cond=False时,new_val在上一行new_val基础上加1 - 当
cond=True时,new_val继承上一行的new_val
输入数据:
| no | cond | val |
|---|---|---|
| 0001/1 | True | 1 |
| 0001/1 | False | 1 |
| 0001/1 | True | 1 |
| 0001/1 | False | 1 |
| 0001/2 | False | 1 |
| 0001/2 | True | 1 |
| 0001/2 | False | 1 |
| 0001/2 | False | 1 |
| 0001/2 | True | 1 |
| 0001/3 | True | 1 |
| 0001/3 | False | 1 |
| 0001/3 | True | 1 |
预期输出:
| no | cond | val | new_val |
|---|---|---|---|
| 0001/1 | True | 1 | 1 |
| 0001/1 | False | 1 | 2 |
| 0001/1 | True | 1 | 2 |
| 0001/1 | False | 1 | 3 |
| 0001/2 | False | 1 | 1 |
| 0001/2 | True | 1 | 1 |
| 0001/2 | False | 1 | 2 |
| 0001/2 | False | 1 | 3 |
| 0001/2 | True | 1 | 3 |
| 0001/3 | True | 1 | 1 |
| 0001/3 | False | 1 | 2 |
| 0001/3 | True | 1 | 2 |
解决方案
方法1:向量化实现(高效)
利用分组标记和累计求和,避免循环,适合大数据量:
import pandas as pd # 构造输入数据(实际使用时替换为你的数据读取逻辑) data = { 'no': ['0001/1']*4 + ['0001/2']*5 + ['0001/3']*3, 'cond': [True, False, True, False, False, True, False, False, True, True, False, True], 'val': [1]*12 } df = pd.DataFrame(data) # 1. 将cond=False转为1,True转为0 df['flag'] = (~df['cond']).astype(int) # 2. 分组后把每组首行的flag设为0 df['flag'] = df.groupby('no')['flag'].transform(lambda x: x.mask(x.index == x.index[0], 0)) # 3. 分组累计求和后加1,得到new_val df['new_val'] = df.groupby('no')['flag'].cumsum() + 1 # 4. 可选:删除中间flag列 df = df.drop('flag', axis=1) print(df)
方法2:自定义分组函数(直观)
逐行计算逻辑,更易理解:
import pandas as pd # 构造输入数据 data = { 'no': ['0001/1']*4 + ['0001/2']*5 + ['0001/3']*3, 'cond': [True, False, True, False, False, True, False, False, True, True, False, True], 'val': [1]*12 } df = pd.DataFrame(data) def compute_new_val(group): new_vals = [1] # 首行固定为1 for cond in group['cond'][1:]: if not cond: new_vals.append(new_vals[-1] + 1) else: new_vals.append(new_vals[-1]) group['new_val'] = new_vals return group df = df.groupby('no', group_keys=False).apply(compute_new_val) print(df)
两种方法均能得到符合预期的结果,根据数据规模选择即可。
内容的提问来源于stack exchange,提问作者king Jude
相关产品推荐
相关产品推荐

