
本文介绍如何在 Pandas 中对列 C2 的连续相同值块(而非全局相同值)进行分组,并计算每组对应 C1 列的均值,适用于时间序列、状态变化日志等需保留原始顺序的场景。
本文介绍如何在 pandas 中对列 c2 的**连续相同值块**(而非全局相同值)进行分组,并计算每组对应 c1 列的均值,适用于时间序列、状态变化日志等需保留原始顺序的场景。
在数据分析中,常遇到需要按「连续状态」而非「全局类别」聚合的需求。例如:传感器每秒上报状态(C2)及测量值(C1),我们希望计算每次状态持续期间的平均测量值——此时不能直接 df.groupby('C2')['C1'].mean(),因为那会把所有 C2=10 的行(无论是否连续)合并计算,而题目要求的是按 C2 值的连续段分别聚合。
核心思路是:为每一组连续相同的 C2 值生成唯一组 ID。Pandas 提供了简洁高效的实现方式——利用 Series.ne(Series.shift()) 标识值变化点,再通过 .cumsum() 累计生成分组标签:
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]
})
# 步骤解析:构造连续分组键
group_id = df['C2'].ne(df['C2'].shift()).cumsum()
# group_id: [1, 1, 2, 3, 3, 4, 4, 4] → 每个连续段拥有独立整数标签
# 方法一:使用 agg() 一次性聚合多列(推荐,更清晰)
result = df.groupby(group_id, as_index=False).agg({
'C1': 'mean',
'C2': 'first' # 取每组首项,确保 C2 值与该连续段一致
}).round(6) # 可选:控制小数位数
print(result)输出:
C1 C2 0 15.0 10 1 30.0 16 2 5.5 23 3 4.666667 10
✅ 优势说明:
-
as_index=False直接返回 DataFrame,避免后续reset_index(); -
agg({'C1': 'mean', 'C2': 'first'})语义明确,且自动保持列名与原始顺序; - 不依赖
sort=False或droplevel(),代码更鲁棒、易维护。
⚠️ 注意事项:
- 切勿使用
df.groupby('C2').mean()—— 它会将所有 C2=10 的行(第0、1、5、6、7行)统一计算均值(10+20+8+4+2)/5 = 8.8,与题目要求的15.0(前两行)、4.67(后三行)完全不符; -
groupby(..., sort=False)在此场景非必需,因cumsum()生成的组 ID 本就按原始顺序递增; - 若数据含缺失值(NaN),
ne(shift())会将首个 NaN 视为“变化”,建议提前用fillna()处理或明确业务逻辑。
总结:识别连续段的本质是「检测值变更」,s.ne(s.shift()).cumsum() 是 Pandas 中的标准范式。结合 agg() 多列聚合,即可一行代码优雅解决此类“按状态持续期统计”的典型问题。

















