这是我想用numpy实现的算法:
对于给定的1D数组,计算滑动窗口的最大值和最小值。 创建一个新数组,第一个值等于给定数组中的第一个值。 对于每个后续值,从滑动窗口剪切插入新数组中的前一个值在最小值和最大值之间。
举一个例子,让我们取数组a=[3, 4, 5, 4, 3, 2, 3, 3]
和一个大小为3的滑动窗口。我们找到最小值和最大值:
min = [3, 4, 3, 2, 2, 2]
max = [5, 5, 5, 4, 3, 3]
现在我们的输出数组将从a
的第一个元素开始,所以它是3
。对于下一个值,我在4和5之间剪切3(插入的最后一个值)(在索引1处找到最小值和最大值)。结果是4.对于下一个值,我在3和5之间剪辑4.它仍然是4.依此类推。所以我们终于有了:
output = [3, 4, 4, 4, 3, 3]
我无法找到避免在代码中使用python for循环的方法。这就是我现在所拥有的:
def second_window(array, samples):
sample_idx = samples - 1
output = np.zeros_like(array[0:-sample_idx])
start, stop = 0, len(array)
last_value = array[0]
# Sliding window is a deque of length 'samples'.
sliding_window = deque(array[start : start+sample_idx], samples)
for i in xrange( stop - start - sample_idx):
# Get the next value in sliding window. After the first loop,
# the left value gets discarded automatically.
sliding_window.append(array[start + i + sample_idx])
min_value, max_value = min(sliding_window), max(sliding_window)
# Clip the last value between sliding window min and max
last_value = min( max(last_value, min_value), max_value)
output[start + i] = last_value
return output
是否有可能只用numpy来实现这个结果?
答案 0 :(得分:2)
我认为你不能。你有时可以使用无缓冲的ufunc进行这种迭代计算,但事实并非如此。但是,让我精心设计......
好的,首先窗口的最小/最大计算可以更快地完成:
>>> a = np.array([3, 4, 5, 4, 3, 2, 3, 3])
>>> len_a = len(a)
>>> win = 3
>>> win_a = as_strided(a, shape=(len_a-win+1, win), strides=a.strides*2)
>>> win_a
array([[3, 4, 5],
[4, 5, 4],
[5, 4, 3],
[4, 3, 2],
[3, 2, 3],
[2, 3, 3]])
>>> min_ = np.min(win_a, axis=-1)
>>> max_ = np.max(win_a, axis=-1)
现在,让我们创建并填充输出数组:
>>> out = np.empty((len_a-win+1,), dtype=a.dtype)
>>> out[0] = a[0]
如果np.clip
表示ufunc,我们可以尝试这样做:
>>> np.clip(out[:-1], min_[1:], max_[1:], out=out[1:])
array([4, 3, 3, 3, 3])
>>> out
array([3, 4, 3, 3, 3, 3])
但是这不起作用,因为np.clip
不是ufunc,并且似乎有一些缓冲。
如果您分别应用np.minimum
和np.maximum
,那么它并不总是有效:
>>> np.minimum(out[:-1], max_[1:], out=out[1:])
array([3, 3, 3, 3, 3])
>>> np.maximum(out[1:], min_[1:], out=out[1:])
array([4, 3, 3, 3, 3])
>>> out
array([3, 4, 3, 3, 3, 3])
虽然对于你的特殊情况,逆转另一个确实有效:
>>> np.maximum(out[:-1], min_[1:], out=out[1:])
array([4, 4, 4, 4, 4])
>>> np.minimum(out[1:], max_[1:], out=out[1:])
array([4, 4, 4, 3, 3])
>>> out
array([3, 4, 4, 4, 3, 3])
答案 1 :(得分:0)
您可以使用numpy.clip
以矢量化方式执行剪切操作,但计算移动窗口的最小值和最大值将需要一些Python循环和一个像您已经实现的deque或堆栈结构
有关该方法的更多示例,请参阅以下问题: