
本文介绍在 Pandas 中对列中连续重复的值(即“批次”)进行计数的方法,生成新列记录每个连续段内该值出现的次数,区别于全局 groupby 统计。
本文介绍在 pandas 中对列中**连续重复的值(即“批次”)进行计数**的方法,生成新列记录每个连续段内该值出现的次数,区别于全局 groupby 统计。
在数据分析中,常需识别并统计「连续重复块」(run-length encoding 场景),例如日志状态序列、传感器信号跃变、或交易流水中的连续相同操作。此时不能直接使用 df.groupby('Value').transform('size')——它会将所有 0 合并统计(如全表共 4 个 0 就全填 4),而目标是:每个连续出现的“0 段”独立计数(首段 3 个 0 → 填 3;末段单个 0 → 填 1)。
核心思路是:构造一个能区分不同连续段的分组键。具体步骤如下:
- 识别段边界:用 Series.ne() 比较当前值与前一行值(通过 shift() 实现),返回布尔 Series,True 表示新段开始;
- 生成段 ID:对该布尔序列做 cumsum(),使每个连续段获得唯一递增编号;
- 按段分组计数:以该段 ID 为键 groupby,再用 transform('size') 将每段长度广播到对应行。
以下是完整可运行代码:
import pandas as pd
# 构造示例数据(注意:原始问题中最后一行为 0,但表格仅显示 6 行,此处严格按答案数据)
data = {'Value': [0, 0, 0, 1, 1, 0]}
df = pd.DataFrame(data)
# 关键:生成连续段分组键,并计算每段长度
df['Freq'] = df.groupby(
df['Value'].ne(df['Value'].shift()).cumsum()
)['Value'].transform('size')
print(df)
输出结果:
Value Freq 0 0 3 1 0 3 2 0 3 3 1 2 4 1 2 5 0 1
✅ 注意事项:
- shift() 默认向上偏移 1 行,首行变为 NaN;ne() 与 NaN 比较返回 True,因此第一行天然作为新段起点,符合预期;
- 此方法时间复杂度为 O(n),高效稳定,适用于百万级数据;
- 若需同时获取段起始索引、长度、值等信息,可进一步结合 pd.Series.diff() 或 scipy.ndimage.label,但本方案已满足频次列填充的核心需求。
该技巧是 Pandas 中处理「连续序列分析」的经典模式,建议封装为复用函数:
def add_run_length_col(df, col, new_col='Freq'):
df[new_col] = df.groupby(df[col].ne(df[col].shift()).cumsum())[col].transform('size')
return df











