如何提取pandas DataFrame指定起止值的单调递增连续切片
pandas提取指定起止值的单调递增连续切片
匹配规则
- 切片严格以设定的起始值开头、终止值结尾
- 切片内
speed列数值单调递增 - 忽略切片范围外的所有其他数据
实现逻辑
使用diff()、cummax()类方案结果异常的核心原因是未提前对连续递增片段做分段切割,跨非递增区间的判断会导致逻辑混乱,正确处理步骤如下:
- 第一步:识别所有连续单调递增的数据段,只要当前行
speed值小于前一行,就标记为递增中断、新段开启,给每个独立的递增段分配唯一ID - 第二步:定位所有值等于起始值的位置作为候选起点
- 第三步:逐个检查候选起点所属的递增段,若段内存在目标终止值,则截取从起点位置到终止值位置的连续行即为结果,分段逻辑已经天然保证片段内数据单调递增,无需额外做单调性校验
代码实现
import pandas as pd import numpy as np # 示例测试数据 speed = [0,1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,14,13,11,12,15,12,14,16,11,10,9,5,12,20,21,22,25,27,32,34,35,30,20] df = pd.DataFrame(speed, columns=['speed']) def get_target_slice(df, start_val, end_val, target_col='speed'): # 标记递增断点,生成连续递增段ID is_decrease = df[target_col].diff() < 0 seg_mark = is_decrease.cumsum() # 遍历所有候选起点 for start_idx in df.index[df[target_col] == start_val]: current_seg_id = seg_mark.loc[start_idx] # 提取起点之后同属一个递增段的所有数据 current_seg_data = df.loc[start_idx:][seg_mark.loc[start_idx:] == current_seg_id, target_col] # 检查当前段是否包含终止值 if end_val in current_seg_data.values: end_idx = current_seg_data[current_seg_data == end_val].index[0] return df.loc[start_idx:end_idx, [target_col]].reset_index(drop=True) # 无符合条件片段时返回空表 return pd.DataFrame(columns=[target_col]) # 测试:起始值20、终止值35 result = get_target_slice(df, 20, 35) print(result)
输出结果
speed 0 20 1 21 2 22 3 25 4 27 5 32 6 34 7 35
和预期结果完全匹配。
性能说明
全表仅做一次向量化差分、累计求和运算,后续仅遍历候选起点位置,无全表逐行循环,百万行级大型DataFrame也可以快速处理。
内容的提问来源于stack exchange,提问作者SomeOne
相关产品推荐
相关产品推荐

