Python计算连续未变化bin段内指标的局部最小值与最大值
连续相同bin段计算局部最值实现方案
核心逻辑是先识别连续相同bin的分段,给每个分段分配唯一标识,再按分段计算butter列的最小值、最大值并回填到每一行,天然支持bin递增、递减、跨号跳变的所有场景。
基于Pandas的最简实现(推荐)
代码简洁易维护,百万行级数据处理效率足够:
import pandas as pd import numpy as np # 替换为你自己的数据读取逻辑,比如pd.read_csv、从数据库读取等 # df = pd.DataFrame(你的原始数据) # 1. 生成分组ID:当前行bin与上一行不同时,分组ID累加1 df['group_id'] = (df['bin'] != df['bin'].shift(1)).cumsum() # 2. 按分组计算每个连续bin段的butter最值,直接回填到每一行 df['min'] = df.groupby('group_id')['butter'].transform('min') df['max'] = df.groupby('group_id')['butter'].transform('max') # 不需要中间列可直接删除 df.drop(columns='group_id', inplace=True)
原理说明
shift(1)将bin列向下偏移1行,逐行对比当前bin和上一行bin是否相等,不等则说明到达新的连续分段- 布尔序列的
cumsum()累加操作会自动给每个连续分段分配独立的递增ID,完全不受bin值大小、变化方向、跳号的影响 transform方法会把分组聚合得到的min/max值按原索引映射回每一行,无需额外做表合并操作
运行后输出的结果和你给出的预期格式完全一致:bin=3的单行列min/max均为1.041967,连续8行bin=4的段min为1.041966、max为1.041975,后续分段计算结果均匹配需求。
纯Numpy实现版本
如果不想依赖pandas的分组逻辑,可以用纯numpy数组操作实现:
bin_arr = df['bin'].to_numpy() butter_arr = df['butter'].to_numpy() # 定位bin值变化的分割点 split_pos = np.where(np.diff(bin_arr) != 0)[0] + 1 butter_groups = np.split(butter_arr, split_pos) # 逐组计算最值并拼接为和原表等长的数组 df['min'] = np.concatenate([np.full(len(g), g.min()) for g in butter_groups]) df['max'] = np.concatenate([np.full(len(g), g.max()) for g in butter_groups])
你之前尝试的
np.diff+np.sign+np.where思路本质也是在找分段边界,但额外处理符号会增加逻辑复杂度,遇到bin跳号的场景还容易出现判断错误,不如直接对比相邻bin是否相等的逻辑鲁棒。
内容的提问来源于stack exchange,提问作者notsure
相关产品推荐
相关产品推荐

