我有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”情况下的值,
d a0 a1 a2 newcol
1.5 10.0 5.0 1.0 3.0
0.8 10.0 2.0 0.0 3.6
newcol是[int(d)]和[int(d + 1)]之间的加权平均值,例如当d = 0.8时,newcol = 0.2 * a0 + 0.8 * a1因为0.8是0到1之间的80%
我发现可以使用np.interp,但是我没办法将三个列名放在变量中:
df["newcol"]=np.interp(df["d"],[0,1,2], [100,200,300])
确实会给我
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_base.py”,第1271行,在interp中 return compiled_interp(x,xp,fp,left,right) ValueError:对象太深,不适合所需的数组
有没有办法在每一行使用不同的矢量值?你能想到任何解决方法吗?
基本上,我找不到根据定义创建这个新列的方法:
x =列“d”中的值是分段线性的函数 在给定点之间,这些点的值在“ai”列中描述
编辑:以前,我使用了scipy.interp1d,这不是内存效率,评论帮我部分解决了我的问题
Edit2:
我尝试了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次左右,所以我想我有一个主要的优化问题。我在DataFrame上工作的哪个部分做错了?
答案 0 :(得分:0)
可能有点太晚了,但我会使用np.interpolate和pandas'应用功能。在您的示例中创建DataFrame:
t = pd.DataFrame([[1.5,10,5,1],[0.8,10,2,0]], columns=['d', 'a0', 'a1', 'a2'])
然后是apply函数:
t.apply(lambda x: np.interp(x.d, [0,1,2], x['a0':]), axis=1)
产生:
0 3.0
1 3.6
dtype: float64
这完全适用于"普通"数据集。但是,DataFrame的大小可能需要更好/更优化的解决方案。处理时间线性缩放,我的机器以每秒10000行的速度计时,这意味着3百万的时间为5分钟......
答案 1 :(得分:0)
好的,我有第二个解决方案,它使用了numexpr模块。这种方法更具体,但也更快。我已经测量了100万行需要733毫秒的完整过程,这还不错......
所以我们像以前一样拥有原始的DataFrame:
t = pd.DataFrame([[1.5,10,5,1],[0.8,10,2,0]], columns=['d', 'a0', 'a1', 'a2'])
我们导入模块并使用它,但它要求我们将两个情况分开,我们将使用'a0'和'a1'或'a1'和'a2'作为线性插值的下限/上限。我们还准备了数字,以便它们可以被馈送到相同的评估(因此-1)。我们通过创建具有插值(最初:'d')的3个数组和限制来实现,具体取决于“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)