如何将Pandas DataFrame的y值插值到另一DataFrame的x轴?
将DataFrame的y值插值到另一个DataFrame的x轴上
我有两个存在重叠(不一定完全重叠)的DataFrame,需要将第一个DataFrame的y值插值到第二个的x轴上,最终得到x列与第二个DataFrame完全一致的结果。实际场景中,两个DataFrame的x值可能是非均匀间隔的,部分值完全匹配、部分不匹配,且第一个DataFrame会包含多列y值(如y1、y2等)。
示例代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt def equation(x): return 0.5 * x + 1 def make_df(x, equation, columns=["x", "y"]): y = equation(x) df = np.c_[x, y] df = pd.DataFrame(df, columns=columns) return df # df1 xx = np.linspace(0, 10, 100) df1 = make_df(xx, equation) # df2 xx = np.linspace(2.1, 10.1, 80) df2 = make_df(xx, equation)
尝试过的方法及问题
我尝试过拼接两个DataFrame再插值的方式:
df3 = pd.DataFrame() df3['x'] = df2['x'] df3['y'] = np.nan temp = pd.concat([df1,df3]).sort_values(by=['x']).interpolate()
但在重新索引时遇到问题。后来找到接近可行的方案:
temp = temp.set_index('x').drop_duplicates().reindex(df2['x']).reset_index()
但在真实数据中,即便用df[df.duplicated(keep=False)]检查不到重复值,调用reindex时仍会报错ValueError: cannot reindex on an axis with duplicate labels,即使设置极低容差(1e-8)也无法解决。
解决方案
方法1:使用SciPy插值函数(推荐处理多列y值)
利用scipy.interpolate.interp1d可以直接基于df1的x和y值,对df2的x进行插值,无需处理DataFrame拼接的重复问题,且支持多列y值:
from scipy.interpolate import interp1d # 提取df1的x和y列(支持多列y,比如y1、y2) x1 = df1['x'].values y_cols = [col for col in df1.columns if col != 'x'] # 创建插值函数,默认线性插值,可指定kind参数(如'quadratic'二次插值) interp_funcs = {col: interp1d(x1, df1[col].values, bounds_error=False, fill_value="extrapolate") for col in y_cols} # 对df2的x进行插值,生成结果DataFrame result = df2[['x']].copy() for col in y_cols: result[col] = interp_funcs[col](df2['x'].values)
bounds_error=False:当df2的x超出df1的x范围时不报错,配合fill_value="extrapolate"可以外插值(如果不需要外插,可设fill_value=np.nan)。- 支持多列y值,只需遍历非x列即可。
方法2:优化Pandas处理流程(解决重复标签问题)
如果坚持用Pandas处理,需要确保索引绝对无重复,可通过对x值进行微小精度处理或去重时更严格:
# 合并df1和df2的x,去重并排序 combined_x = pd.concat([df1['x'], df2['x']]).drop_duplicates(keep='first').sort_values() # 创建包含所有x的临时DataFrame,合并df1的数据,插值 temp = pd.DataFrame({'x': combined_x}).merge(df1, on='x', how='left').interpolate(method='linear', limit_direction='both') # 仅保留df2的x值 result = temp[temp['x'].isin(df2['x'])].reset_index(drop=True) # 确保和df2的x顺序一致(因为isin可能打乱顺序) result = result.set_index('x').reindex(df2['x']).reset_index()
如果仍遇到重复标签问题,可先对x值进行四舍五入(根据数据精度调整小数位数):
# 对x值进行精度处理,避免浮点误差导致的"伪重复" df1['x'] = df1['x'].round(6) df2['x'] = df2['x'].round(6)
浮点型数据的精度误差常会导致看似不重复的数值被识别为重复,通过四舍五入到合理的小数位数可以解决这类问题。
内容的提问来源于stack exchange,提问作者Morten Nissov
相关产品推荐
相关产品推荐

