Python 插值:使用np.interp和更改的值

Python 插值:使用np.interp和更改的值,python,pandas,scipy,Python,Pandas,Scipy,我有一个300万行数据框,其中包含不同的值: d a0 a1 a2 0.5 10.0 5.0 1.0 0.8 10.0 2.0 0.0 我想用线性插值(a0,a1,a2)填充第四列,取“d”情况下的值 newcol是a[int(d)]和a[int(d+1)]之间的加权平均值,例如,当d=0.8时,newcol=0.2*a0+0.8*a1,因为0.8是0和1之间的80% 我发现可以使用np.interp,但我无法将这三个列名放入变量): 真的

我有一个300万行数据框,其中包含不同的值:

d    a0    a1    a2
0.5    10.0    5.0    1.0
0.8    10.0    2.0    0.0
我想用线性插值(a0,a1,a2)填充第四列,取“d”情况下的值

newcol是a[int(d)]和a[int(d+1)]之间的加权平均值,例如,当d=0.8时,newcol=0.2*a0+0.8*a1,因为0.8是0和1之间的80%

我发现可以使用np.interp,但我无法将这三个列名放入变量):

真的会给我

d    a0    a1    a2    newcol
1.5    10.0    5.0    1.0    250.0
0.8    10.0    2.0    0.0    180.0
但我无法指定值向量的变化:

df["newcol"]=np.interp(df["d"],[0,1,2], df[["a0","a1","a2"]])
给我以下回溯:

文件“C:\Python27\lib\site packages\numpy\lib\function\u base.py”,第1271行,在interp中 返回编译的_interp(x,xp,fp,左,右) ValueError:对象对于所需数组太深

有没有办法对每行的值使用不同的向量?你能想出解决办法吗

基本上,我无法根据定义创建此新列:

分段线性函数的x=列“d”中的值是多少 在给定点之间,这些点的值在“ai”列中描述

编辑:以前,我使用了scipy.interp1d,它不节省内存,该评论帮助我部分解决了我的问题

编辑2:

我尝试了来自ev br的方法,该方法声明我必须尝试自己编写循环代码

for i in range(len(tps)):
    columns=["a1","a2","a3"]
    length=len(columns)
    x=np.maximum(0,np.minimum(df.ix[i,"d"],len-2))
    xint = np.int(x)
    xfrac = x-xint
    name1=columns[xint]
    name2=columns[xint+1]
    tps.ix[i,"Multiplier"]=df.ix[i,name1]+xfrac*(df.ix[i,name2]-tps.ix[i,name1])  

上面的循环大约每秒循环50次,所以我想我有一个主要的优化问题。在数据帧上工作的哪一部分我做错了

可能来得有点晚,但我会使用np.interpolate和pandas的apply函数。在您的示例中创建数据帧:

t = pd.DataFrame([[1.5,10,5,1],[0.8,10,2,0]], columns=['d', 'a0', 'a1', 'a2'])
然后是应用功能:

t.apply(lambda x: np.interp(x.d, [0,1,2], x['a0':]), axis=1)
这将产生:

0    3.0
1    3.6
dtype: float64

这在“正常”数据集上是完全可用的。但是,数据帧的大小可能需要更好/更优化的解决方案。处理时间呈线性扩展,我的机器每秒时钟为10000行,这意味着300万行需要5分钟…

好的,我有第二个解决方案,它使用numexpr模块。这种方法更加具体,但速度也更快。我已经测量了整个过程,100万行需要733毫秒,这还不错

因此,我们与之前一样拥有原始数据帧:

t = pd.DataFrame([[1.5,10,5,1],[0.8,10,2,0]], columns=['d', 'a0', 'a1', 'a2'])
我们导入模块并使用它,但它要求我们将使用“a0”和“a1”或“a1”和“a2”作为线性插值的下限/上限的两种情况分开。我们还准备了数字,以便将它们输入到相同的评估中(因此为-1)。我们通过创建3个具有插值值(最初为:“d”)和限制的数组来实现这一点,具体取决于“d”的值。因此,我们:

import numexpr as ne

lim = np.where(t.d > 1, [t.d-1, t.a1, t.a2], [t.d, t.a0, t.a1])
然后我们计算简单线性插值表达式,最后将其添加为新列,如下所示:

x = ne.evaluate('(1-x)*a+x*b', local_dict={'x': lim[0], 'a': lim[1], 'b': lim[2]})
t['IP'] = np.where(t.d > 1, x+1, x)

如果您只需要线性插值,
numpy.interp
可能更合理。或者,您可以按照您显示的方式计算apply函数中的加权平均值。感谢您的评论,我现在使用np.interp,我更接近我的答案,因此我相应地修改了我的问题(现在更清楚了)既然你改变了这个问题,我对编写一个详细的回答就失去了兴趣,但基本上:在数据帧的行上使用for循环为自己编写一个解决方案,然后把它交给cython,就一切就绪了。
import numexpr as ne

lim = np.where(t.d > 1, [t.d-1, t.a1, t.a2], [t.d, t.a0, t.a1])
x = ne.evaluate('(1-x)*a+x*b', local_dict={'x': lim[0], 'a': lim[1], 'b': lim[2]})
t['IP'] = np.where(t.d > 1, x+1, x)