基于日期groupby的Pandas双值插值及最小值对应列提取问询
Pandas分组后实现线性插值与极值提取方案
需求说明
对DataFrame按input_date列分组后,需完成三项处理:
- 基于
val_x1列,对0.25值进行val_y1列的线性插值,得到interp_25; - 基于
val_x1列,对0.75值进行val_y1列的线性插值,得到interp_75; - 提取
p1+p2值最小时对应的val3列值,得到val3_minp1p2。
示例数据
原始DataFrame:
input_date val_x1 val_y1 p1 p2 val3 13/06/2024 0.23 0.17 124 350 0.15 13/06/2024 0.245 0.16 178 298 0.16 13/06/2024 0.276 0.15 192 275 0.17 13/06/2024 0.743 0.22 350 134 0.18 13/06/2024 0.76 0.21 296 184 0.17
期望输出:
input_date interp_25 interp_75 val3_minp1p2 13/06/2024 0.158 0.216 0.15
注:0.158是(0.245,0.16)与(0.276,0.15)在0.25处的线性插值;0.216是(0.743,0.22)与(0.76,0.21)在0.75处的线性插值;val3_minp1p2对应p1+p2最小值374所在行的val3值0.15。
解决方案
使用groupby.apply方法传入自定义函数,相比agg更适合处理这类多步骤的复杂计算。具体实现如下:
代码实现
import pandas as pd from scipy.interpolate import interp1d # 构造示例数据 df = pd.DataFrame({ 'input_date': ['13/06/2024']*5, 'val_x1': [0.23, 0.245, 0.276, 0.743, 0.76], 'val_y1': [0.17, 0.16, 0.15, 0.22, 0.21], 'p1': [124, 178, 192, 350, 296], 'p2': [350, 298, 275, 134, 184], 'val3': [0.15, 0.16, 0.17, 0.18, 0.17] }) def process_group(group): # 先确保val_x1是排序状态(插值需要有序输入) sorted_group = group.sort_values('val_x1') # 1. 计算0.25处的线性插值 f_25 = interp1d(sorted_group['val_x1'], sorted_group['val_y1'], kind='linear', fill_value='extrapolate') interp_25 = round(f_25(0.25).item(), 3) # 2. 计算0.75处的线性插值 f_75 = interp1d(sorted_group['val_x1'], sorted_group['val_y1'], kind='linear', fill_value='extrapolate') interp_75 = round(f_75(0.75).item(), 3) # 3. 提取p1+p2最小时的val3 group['p_sum'] = group['p1'] + group['p2'] val3_minp1p2 = group.loc[group['p_sum'].idxmin(), 'val3'] # 返回当前分组的结果 return pd.Series({ 'interp_25': interp_25, 'interp_75': interp_75, 'val3_minp1p2': val3_minp1p2 }) # 分组执行处理并整理结果 result = df.groupby('input_date').apply(process_group).reset_index() print(result)
代码说明
- 排序处理:插值前对分组内的
val_x1排序,满足interp1d对输入x值单调有序的要求; - 线性插值:用
scipy.interpolate.interp1d构造插值函数,fill_value='extrapolate'可处理目标值超出val_x1范围的情况,不需要外插可改为None; - 极值提取:计算
p1+p2的和,通过idxmin()定位最小值所在行,提取对应val3值; - 结果整合:自定义函数返回包含三个结果的Series,
groupby.apply自动合并各分组结果,reset_index()将input_date转为普通列。
内容的提问来源于stack exchange,提问作者Hotone
相关产品推荐
相关产品推荐

