本文介绍一种高效方法:利用列值差分与累积和,自动识别并切分数据中所有“非递减连续段”,从而将 dataframe 按升序(含相等)的自然断点划分为多个独立子组。
本文介绍一种高效方法:利用列值差分与累积和,自动识别并切分数据中所有“非递减连续段”,从而将 dataframe 按升序(含相等)的自然断点划分为多个独立子组。
在数据分析中,常需根据某列数值的单调性变化对数据进行逻辑分段——例如,将价格序列中每个“持续上涨或持平”的连续区间视为一个业务周期,一旦出现下跌即开启新周期。Pandas 本身不提供直接的“升序连续段分组”函数,但可通过组合 diff()、布尔运算和 cumsum() 巧妙实现。
核心思路是:检测“破坏升序/平序”的位置(即当前值 。具体步骤如下:
- 计算列 a 的一阶差分:df['a'].diff() → 得到 [NaN, 4, 6, -10, 2, -7, -2];
- 判断哪些位置发生了下降:(df['a'].diff()
- 对布尔结果做累积和:.cumsum() → [0, 0, 0, 1, 1, 2, 3],该结果天然构成分组标签(每遇一次下降,组号 +1);
- 使用该标签调用 groupby(),即可拆分出所有升序连续段。
完整代码示例如下:
import pandas as pd
df = pd.DataFrame({'a': [10, 14, 20, 10, 12, 5, 3]})
# 生成分组标签:每次 a 下降时组号递增
group_labels = (df['a'].diff() <p>输出为:</p><pre class="brush:php;toolbar:false;">Group 0:
a
0 10
1 14
2 20
Group 1:
a
3 10
4 12
Group 2:
a
5 5
Group 3:
a
6 3
✅ 关键说明:
- 此方法严格遵循“升序或相等即延续当前组,严格下降才开启新组”的逻辑;
- diff() 默认计算 current - previous,因此 diff()
- cumsum() 对布尔值按 True→1, False→0 处理,天然适配分组编号需求;
- 若需保留原始索引(如后续需回溯位置),推荐使用 list(df.groupby(...)) 而非重置索引。
该方案简洁、向量化、无循环,适用于百万级数据,是 Pandas 中处理单调性分段问题的标准实践。










