使用interp1d

时间:2017-12-01 13:53:15

标签: python pandas scipy interpolation

我在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'])

但是,报告的错误是数组的长度不相等。

1 个答案:

答案 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)