2016-02-02 45 views
0

我有一個3百萬行數據框中包含不同的值:大熊貓插值:使用np.interp不斷變化值

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)]和a [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"]]) 

給了我下面的回溯:

File "C:\Python27\lib\site-packages\numpy\lib\function_base.py", line 1271, in interp return compiled_interp(x, xp, fp, left, right) ValueError: object too deep for desired array

有什麼辦法在每行使用的值不同的載體?你能想到任何解決方法嗎?

基本上,我找不到任何方法來創建基於定義這個新列:

What is the value in x = column "d" of the function that is piecewise linear between given points and whose values at these points are described in the columns "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

如果你只需要線性插值,'numpy.interp'可能理智的。 –

+0

或者,您可以按照您展示的方式計算應用函數內的加權平均值。 – Evert

+0

感謝您的評論,我現在使用np.interp,我更接近我的答案,所以我相應地修改了我的問題(現在更清晰) – WNG

回答

0

它可能會來得太晚,但我會使用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 

這是 「正常」 的數據集非常有用的。但是,DataFrame的大小可能需要更好/更優化的解決方案。處理時間線性地縮放,我的機器時鐘以每秒10000行,這意味着5分鐘爲300萬...

0

好的,我有第二個解決方案,它使用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)