基于status_process列批量填充DataFrame的sprvk_type列值
问题:按流程填充DataFrame的sprvk_type列
我有如下拼接后的DataFrame:
import pandas as pd import datetime as dt d = { 'oper_dt' : [dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19)] , 'oper_dttm' : [dt.datetime(2024,1,19,9,43,43), dt.datetime(2024,1,19,9,43,50), dt.datetime(2024,1,19,9,43,57), dt.datetime(2024,1,19,9,44,9)] , 'user_id' : [111111, 111111, 111111, 111111] , 'status_process' : ['Start', None, 'Success', None] , 'status_type' : [None, None, 'ready', 'print'] , 'sprvk_type' : [None, '2NDFL', None, None] } d1 = { 'oper_dt' : [dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19)] , 'oper_dttm' : [dt.datetime(2024,1,19,9,47,47), dt.datetime(2024,1,19,9,48,50), dt.datetime(2024,1,19,9,49,5)] , 'user_id' : [111111, 111111, 111111] , 'status_process' : ['Start', None, 'Success'] , 'status_type' : [None, None, 'ready'] , 'sprvk_type' : [None, 'TAX_DEDUCTION', None] } df = pd.concat([pd.DataFrame(d), pd.DataFrame(d1)])
需求:根据status_process列的"Start"标记划分流程("Start"代表新流程开始),将每个流程内sprvk_type的有效值复制填充到该流程的所有行,最终得到如下格式的DataFrame:
import pandas as pd import datetime as dt d = { 'oper_dt' : [dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19)] , 'oper_dttm' : [dt.datetime(2024,1,19,9,43,43), dt.datetime(2024,1,19,9,43,50), dt.datetime(2024,1,19,9,43,57), dt.datetime(2024,1,19,9,44,9)] , 'user_id' : [111111, 111111, 111111, 111111] , 'status_process' : ['Start', None, 'Success', None] , 'status_type' : [None, None, 'ready', 'print'] , 'sprvk_type' : ['2NDFL', '2NDFL', '2NDFL', '2NDFL'] } d1 = { 'oper_dt' : [dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19)] , 'oper_dttm' : [dt.datetime(2024,1,19,9,47,47), dt.datetime(2024,1,19,9,48,50), dt.datetime(2024,1,19,9,49,5)] , 'user_id' : [111111, 111111, 111111] , 'status_process' : ['Start', None, 'Success'] , 'status_type' : [None, None, 'ready'] , 'sprvk_type' : ['TAX_DEDUCTION', 'TAX_DEDUCTION', 'TAX_DEDUCTION'] } result_df = pd.concat([pd.DataFrame(d), pd.DataFrame(d1)])
解决方案
通过以下两步即可实现需求:
- 标记流程分组:根据
status_process列的"Start"值,生成每个流程的唯一分组ID。 - 按分组填充有效值:在每个分组内,将
sprvk_type的有效值向前、向后填充,覆盖所有空值。
完整代码如下:
import pandas as pd import datetime as dt # 构建原始DataFrame d = { 'oper_dt' : [dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19)] , 'oper_dttm' : [dt.datetime(2024,1,19,9,43,43), dt.datetime(2024,1,19,9,43,50), dt.datetime(2024,1,19,9,43,57), dt.datetime(2024,1,19,9,44,9)] , 'user_id' : [111111, 111111, 111111, 111111] , 'status_process' : ['Start', None, 'Success', None] , 'status_type' : [None, None, 'ready', 'print'] , 'sprvk_type' : [None, '2NDFL', None, None] } d1 = { 'oper_dt' : [dt.date(2024,1,19), dt.date(2024,1,19), dt.date(2024,1,19)] , 'oper_dttm' : [dt.datetime(2024,1,19,9,47,47), dt.datetime(2024,1,19,9,48,50), dt.datetime(2024,1,19,9,49,5)] , 'user_id' : [111111, 111111, 111111] , 'status_process' : ['Start', None, 'Success'] , 'status_type' : [None, None, 'ready'] , 'sprvk_type' : [None, 'TAX_DEDUCTION', None] } df = pd.concat([pd.DataFrame(d), pd.DataFrame(d1)]) # 生成流程分组ID df['process_group'] = df['status_process'].eq('Start').cumsum() # 按分组填充sprvk_type的有效值 df['sprvk_type'] = df.groupby('process_group')['sprvk_type'].transform(lambda x: x.ffill().bfill()) # 可选:删除临时的分组列 df = df.drop('process_group', axis=1) print(df)
代码说明
df['status_process'].eq('Start').cumsum():判断每行是否为流程起点,通过累加生成唯一的分组ID,确保每个流程对应独立分组。groupby('process_group')['sprvk_type'].transform(lambda x: x.ffill().bfill()):先向前填充(ffill())再向后填充(bfill()),保证分组内所有行都被有效值覆盖。
内容的提问来源于stack exchange,提问作者user16016201
相关产品推荐
相关产品推荐

