You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas如何基于其他列与前序行值重排DataFrame列序号

pandas按事件段重编号day列实现方案

原始数据与需求

原始DataFrame结构如下:

date          day_of_week   day
2021-01-01    3              1
2021-01-02    4              2 
2021-01-03    5              0
2021-01-04    6              1
2021-01-05    7              2
2021-01-06    1              3
2021-01-07    2              0
2021-01-08    3              0

编号规则:

  • 识别所有连续day>0的行组成独立事件段,day=0为段分隔符,值保持0不变
  • 每个事件段根据段首行的day_of_week值确定编号起始基数:
    • 段首day_of_week < 4(周四前起始):段内非0day值从20开始依次递增
    • 段首day_of_week >= 4(周四及之后起始):段内非0day值从30开始依次递增
      目标输出结果:
date          day_of_week   day
2021-01-01    3              20
2021-01-02    4              21 
2021-01-03    5              0
2021-01-04    6              30
2021-01-05    7              31
2021-01-06    1              32
2021-01-07    2              0
2021-01-08    3              0

实现代码

不需要逐行遍历,用pandas连续值分组+向量化运算即可高效实现:

import pandas as pd
import numpy as np

# 1. 构造原始测试数据
df = pd.DataFrame({
    'date': ['2021-01-01','2021-01-02','2021-01-03','2021-01-04','2021-01-05','2021-01-06','2021-01-07','2021-01-08'],
    'day_of_week': [3,4,5,6,7,1,2,3],
    'day': [1,2,0,1,2,3,0,0]
})

# 2. 标记连续事件段:遇到day=0则事件id递增
df['event_id'] = (df['day'] == 0).cumsum()
non_zero_mask = df['day'] > 0

# 3. 匹配每个事件段的编号起始基数
base_config = df[non_zero_mask].groupby('event_id')['day_of_week'].first().apply(
    lambda x: 20 if x < 4 else 30
)
df['base_num'] = df['event_id'].map(base_config)

# 4. 段内递增生成新编号,0值保持不变
df.loc[non_zero_mask, 'day'] = df[non_zero_mask].groupby('event_id').cumcount() + df.loc[non_zero_mask, 'base_num']
df['day'] = df['day'].fillna(0).astype(int)

# 5. 删除临时列
df = df.drop(columns=['event_id', 'base_num'])

运行后打印df即可得到目标结果。
注:该实现为pandas原生向量化写法,运行效率远高于逐行遍历,十万级以上数据量下性能差距尤为明显。


内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 01:03:17