2017-03-01 60 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()