计算numpy中移动窗口的值

时间:2018-07-31 03:42:45

标签: python numpy

我有一个CSV,其数据具有多列中的数字值。我的目标是根据特定列中的下5个值是否在原始列的下方/上方,在其末尾添加-1、0或1的列。

例如,下面的数据,key: 0.0.0 value: x-y-z key: 0.0.1 value: x-y-z . key: 0.0.59 value: x-y-z . key: 0.1.0 value x-y-z key: 0.1.1 value x-y-z key: 30.0.0 value: y-x-z . . key: 30.0.59 value: y-x-z . key: 30.1.0 value: y-x-z key: 30.1.1 value: y-x-z key: 30.1.2 value: y-x-z . . key: 30.1.59 value: y-x-z key: 30.2.0 value: y-x-z key: 30.2.1 value: y-x-z key: 30-2.3 value: y-x-z . . key: 60.0.0 value: z-y-x key: 60.0.1 value: z-y-x key: 60.0.2 value: z-y-x . . key: 60.0.59 value: z-y-x key: 60.1.0 value: z-y-x key: 60.1.1 value: z-y-x . . ,如果开始>可以在同一列中结束,那么我可以执行一次操作,但是我该如何展望?我想要一个移动列,如果起始值是接下来5个结束值中的最低值,则放置1。如果起始位置是接下来5个结束值中的最高值,则放置-1。如果最终值在上下,则返回0。

np.where

2 个答案:

答案 0 :(得分:1)

In [142]: txt = """0       5      1   // the start value here is the lowest of
     ...:  the next 5     end values
     ...: 5       10     1   // same as above
     ...: 10      15     1   // same as above
     ...: 15      25     1   // same as above
     ...: 25      30     1   // same as above
     ...: 30      35     0   // end goes up and down so 0 here
     ...: 35      40     0   // same as above
     ...: 40      30    -1   // next are all below 40 so -1 now 
     ...: 30      20
     ...: 20      15
     ...: 15      10    
     ...: 10      5"""
In [143]: data = np.genfromtxt(txt.splitlines(), usecols=[0,1],encoding=None, 
     ...: dtype=int)
In [144]: data
Out[144]: 
array([[ 0,  5],
       [ 5, 10],
       [10, 15],
       [15, 25],
       [25, 30],
       [30, 35],
       [35, 40],
       [40, 30],
       [30, 20],
       [20, 15],
       [15, 10],
       [10,  5]])

编写一个函数来处理一行(接下来的5行):

In [145]: def foo(data,i):
     ...:     start = data[i,0]
     ...:     ends = data[i:i+5,1]
     ...:     if (start<ends).all():
     ...:         return 1
     ...:     if (start>ends).all():
     ...:         return -1
     ...:     else:
     ...:         return 0
     ...:    

测试特定的i-令人惊讶的是,我第一次做对了!通常,对单词的描述进行解释很棘手,而且模棱两可。

In [146]: foo(data,0)
Out[146]: 1
In [147]: foo(data,5)
Out[147]: 0
In [148]: foo(data,7)
Out[148]: -1

现在只需迭代即可获得列表:

In [149]: [foo(data,i) for i in range(8)]
Out[149]: [1, 1, 1, 1, 0, 0, 0, -1]

填充此列表,以便可以将其附加到data上,作为读者(或OP)的练习。

答案 1 :(得分:0)

如果您坚持使用numpy,则可以使用np.lib.stride_tricks.as_strided来解决问题。如果我们将大小为5的额外维度添加到数组中,以便该维度上的跨度将您带到下一个元素,则可以沿该额外维度取最小值和最大值,然后将其与原始数组进行比较。

请记住,as_strided是一门重载的大炮,它会在其他任何事情发生后立即将您射向您的脚:

start = np.array([0,5,10,15,25,30,35,40,30,20,15,10])
view = np.lib.stride_tricks.as_strided(start, shape=(start.size - 4, 5), strides=start.strides * 2, writeable=False)
move = ((start[:-4] == view.min(axis=1)).astype(int) - (start[:-4] == view.max(axis=1)))

IDEOne Link