2017-03-01 59 views
0

我有一個numpy的陣列(其不一定排序)同樣:numpy的/大熊貓差異:傳播DIFF在封閉楠元件

[2.0, 3.0, nan, nan, nan, 5.0] 

欲計算該陣列上的差異。最後一個元素5和第二個元素3的區別是2.我希望這個2的差值分佈在我的numpy數組的隨機南元素上。如果我嘗試numpy.diff(我也嘗試使用蒙版陣列)我得到的結果:

[nan, 1, nan, nan, nan, nan]

它的結果應該是這樣的:

[nan, 1, 0.5, 0.5, 0.5, 0.5] 

UPDATE:

我得到的答案爲以上具體情況而定的答案不是更一般的形式有效。例如,如果我們有尾隨/領先的南,當我們有交替nan和價值。例如:

[nan, nan, 2.0, 3.0, nan, nan, nan, 5.0, nan, 6.0, nan] 
+0

所以,將NaN比其他被輸入數組排序?而且,它的想法是,輸出數組也被排序。 這個想法是輸出[i]是輸入[i]和輸入[i-1]之間差異的平均值,具有nans的特殊情況? – JawguyChooser

+0

第一個問題:不,數組不一定排序,例如可能是[5,11,4,nan,2]。第二個問題:是的,如果輸入[i-1]是南,我們應該檢查輸入[i-2],如果輸入[1-2]不是南,我們將輸入[i]和輸入[i-2 ]同等於輸入[i-1]和輸入[i]。 –

+0

更新案例的預期輸出是什麼? – JawguyChooser

回答

1

感謝魯特格爾Kassies,我一直在尋找到大熊貓,他們有現成的方法來解決這個普遍問題:

數組轉換成數據幀,插值數據幀,並採取DIFF:

import pandas as pd 
    array = [nan, nan, 2.0, 3.0, nan, nan, nan, 5.0, nan, 6.0, nan] 
    df = pd.DataFrame(array) 
    interpolation = df.interpolate() 
    diff = interpolation.diff() 

結果是:

[NaN, NaN, NaN, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0] 
1

在假設你正在試圖做的是映射輸出[I]輸入的差異[i]和輸入[I-1],在特殊情況下,的NaN,要分發跨NaN的這種差異,如果是這樣的想法,我認爲這是你想要什麼:

import numpy as np 

def arrdiffs(a): 
    out = np.array(np.zeros(len(a))) 
    diff=np.nan 
    difflen=0 
    for i,e in enumerate(a): 
     if i==0: 
      # in the first cell we always output nan 
      out[i]=np.nan 
     elif np.isnan(a[i]): 
      # when the input is nan, just increase difflen 
      difflen+=1 
     elif np.isnan(a[i-1]): 
      # when the previous input is nan, but this one isn't 
      # distribute the diff across the previous cells and this one 
      difflen+=1 
      m=float(abs(a[i]-diff)) 
      for j in range(i-difflen+1,i+1): 
       out[j]=m/difflen 
      difflen=0 
      diff=a[i] 
     else: 
      # othewise simply do the diff locally between this cell and 
      # previous 
      out[i]=abs(a[i]-a[i-1]) 
      diff=a[i] # write down diff in case the next input cells are nan 
      difflen=0 

    return out 

a=np.array([2.0,3.0,np.nan,np.nan,np.nan,5.0]) 
print arrdiffs(a) 

編輯:切換到4級空格的標籤,而不是2,扁平化的if/else成elifs, 在每個分支添加了評論。

當我運行這個,我知道你的預期輸出:

$ python arrdiffs.py 
[ nan 1. 0.5 0.5 0.5 0.5] 

編輯:切換差異的初始值np.nan考慮,我們有一系列的NaN啓動的情況下,大概只有我們輸出nan,直到我們達到至少一些初始值。向OP尋求澄清這裏的目標是什麼。在[i-1]是nan但是[i]不是(這是一個bug)的情況下,也將賦值diff切換到[i]。由OP提供的新的測試用例:

[np.nan, np.nan, 2.0, 3.0, np.nan, np.nan, np.nan, 5.0, np.nan, 6.0, np.nan] 

此更新代碼給出:

>>> [ nan nan nan 1. 0.5 0.5 0.5 0.5 0.5 0.5 0. ] 

這是任擇議定書想要什麼?尋求澄清。

+0

當我第一次發佈這個在j上的循環時發生了錯誤。我現在解決這個問題。一定要看當前的版本,當你做循環j,你想從i-difflen + 1,而不是i-difflen – JawguyChooser

1

這應該做的工作:

In [1]: import pandas as pd 

In [2]: import numpy as np 

In [3]: a = [2.0, 3.0, np.nan, np.nan, np.nan, 5.0] 

In [4]: s = pd.Series(a) 

In [5]: result = s.reset_index()\ 
    ...:   .dropna()\ 
    ...:   .diff()\ 
    ...:   .pipe(lambda x: x[0]/x['index'])\ 
    ...:   .reindex(s.index)\ 
    ...:   .fillna(method='bfill') 

In [6]: result[0] = np.nan 

In [7]: result 
Out[7]: 
0 NaN 
1 1.0 
2 0.5 
3 0.5 
4 0.5 
5 0.5 
dtype: float64 
+0

我不認爲這是他正在尋找的答案。你會看到他在OP中的預期輸出。 – JawguyChooser

+0

正如我寫的,你只需要將NA分配給第一個元素。我認爲這是微不足道的,但如果你希望我將它添加到代碼示例 –

1

我只想先插值男的。通過這種方式,您可以在這兩個步驟之間保持一個很好的分隔,例如可以更容易地改變插值方式。

import numpy as np 

a = np.array([2.0, 3.0, np.nan, np.nan, np.nan, 5.0]) 
x = np.arange(a.size) 

a_filled = np.interp(x, x[np.isfinite(a)], a[np.isfinite(a)]) 

np.diff(a_filled) 

# results in 
array([ 1. , 0.5, 0.5, 0.5, 0.5]) 

更多花哨的插值,大熊貓可能是一個很好的選擇,它也有一個Dataframes方法.diff()