
本文介绍如何在 Pandas 中对列 C1 按 C2 的连续相同值段(run-length groups) 分组并计算均值,而非全局或普通 groupby,适用于序列化依赖场景。
本文介绍如何在 pandas 中对列 c1 按 c2 的**连续相同值段(run-length groups)** 分组并计算均值,而非全局或普通 groupby,适用于序列化依赖场景。
在数据分析中,有时我们需要按“连续块”(consecutive runs)而非全部相同值进行聚合。例如,当 C2 列出现 [10, 10, 16, 23, 23, 10, 10, 10] 时,值 10 出现了两次不相邻的连续段(开头两个和末尾三个),应分别计算对应 C1 的均值,而非将所有 C2 == 10 的行合并处理——这正是本问题的核心需求。
实现的关键在于:为每一段连续相同的 C2 值生成唯一组 ID。Pandas 提供了简洁高效的链式方法:
import pandas as pd
df = pd.DataFrame({
'C1': [10, 20, 30, 5, 6, 8, 4, 2],
'C2': [10, 10, 16, 23, 23, 10, 10, 10]
})
# 方法一:使用 agg() —— 推荐(更清晰、易维护)
result = (df.groupby(df['C2'].ne(df['C2'].shift()).cumsum(), as_index=False)
.agg({'C1': 'mean', 'C2': 'first'}))
print(result.round(6))输出:
C1 C2 0 15.0 10 1 30.0 16 2 5.5 23 3 4.666667 10
✅ 原理说明:
-
df['C2'].shift()将 C2 下移一行,用于与原值对齐比较; -
.ne()(即!=)生成布尔序列,标识每次 C2 值发生变化的位置(True表示新段开始); -
.cumsum()对该布尔序列累加,自然形成连续段编号(如[1,1,2,3,3,4,4,4]); - 此编号作为 groupby 的键,确保仅合并物理位置连续且值相同的行块。
⚠️ 注意事项:
- 必须设置
as_index=False(方法一)或显式.reset_index()(方法二),否则结果会丢失原始列结构; -
agg({'C1': 'mean', 'C2': 'first'})安全取每段首个 C2 值,避免误用.last()或.max()引入歧义; - 若需保留更多列(如时间戳),可扩展
agg字典,对非聚合列统一使用'first'或'last'; - 该逻辑不依赖 C2 是否有序,但严格依赖行序——请确保 DataFrame 已按业务逻辑(如时间、索引)正确排序。
? 进阶提示:若后续需还原原始顺序或关联原始索引,可在分组前添加辅助列 df.assign(group_id=...),便于调试与追踪。
总之,df[col].ne(df[col].shift()).cumsum() 是 Pandas 中识别连续值段的黄金模式,配合 groupby().agg() 即可优雅解决此类“上下文敏感均值”问题。

















