我在python中有以下数据帧(df):
X1 X2 Y1 Y2 X YInt
10 20 0.6 1 17 ???
5 50 0.4 1 9 ???
我正在尝试向该数据帧添加一个新列(YInt),该数据帧评估给定X的线性插值Y值以及给定行中给定坐标X1,Y2,X2,Y2。
到目前为止,我有以下代码:
df['YInt'] = interp1d(df[['X1','X2']],df[['Y1','Y2']],bounds_error=False)(df['X'])
但是,报告的错误是数组的长度不相等。
答案 0 :(得分:0)
参见上次修改
您可以将interp1d
功能应用于每一行:
df['YInt'] = df.apply(lambda row:
interp1d([row.X1, row.X2],
[row.Y1, row.Y2],
bounds_error=False
)(row.X),
axis=1)
但是在大型数据帧上这是非常慢的,但我不确定如何优化它。
编辑:
它很难优化,因为你必须进行逐行操作。您应该查看Pandas文档中的Enhancing Performance Guide以获得更多洞察力。但无论如何,使用numba我的设置性能提升了4倍,其方法类似于我之前给出的方法:
@numba.vectorize([numba.float64(numba.float64, # Return type is float
numba.float64, # with 5 float arguments
numba.float64,
numba.float64,
numba.float64)])
def interp_helper_numba(x1, x2, y1, y2, x):
return interp1d([x1, x2], [y1, y2], bounds_error=False)(x)
df['Y'] = interp_helper_numba(df.X1.values, df.X2.values,
df.Y1.values, df.Y2.values,
df.X.values)
Pandas还有pd.Series.interpolate
函数本身包裹scipy.interpolate.interp1d
,但是如果你想使用它,你会遇到同样的问题:你想要逐行插值。
编辑:
由于这只是正常的两点线性插值,因此可以非常轻松地手动计算值:
def manual_interp(x1, x2, y1, y2, x):
return (y1 * (x2 - x) + y2 * (x - x1)) / (x2 - x1)
df['Y'] = manual_interp(df.X1.values, df.X2.values,
df.Y1.values, df.Y2.values,
df.X.values)
在具有1亿行的数据集上测试它,并在一秒钟内完成。 :)
自Rolo想要一个单行代码后的最终编辑:
df['Y'] = (df.Y1.values * (df.X2.values - df.X.values) + df.Y2.values * (df.X.values - df.X1.values)) / (df.X2.values - df.X1.values)