我想识别numpy数组中的元素,它比从索引5开始的前5个元素更大。我用'for'循环写下了这个问题的解决方案。我的问题是如何在没有迭代的情况下解决这个问题呢?这个问题是否存在某些功能?
import numpy as np
values = np.array([160, 140, 152, 142, 143, 186, 152, 145, 165, 152, 143, 148, 196, 152, 145, 157, 152])
indices = []
for i in range(5, len(values)):
if np.all(values[(i-5):i]<values[i]):
indices.append(i)
答案 0 :(得分:2)
一个技巧是计算跨越数组长度的滑动窗口中的最大值,不包括当前元素并与当前元素进行比较。如果当前元素更大,那么我们就有赢家,否则我们不会。
要获得滑动最大值,我们可以使用Scipy's 1D max
过滤器的服务,因此可以实现这样的实现 -
from scipy.ndimage.filters import maximum_filter1d as maxf
def greater_than_all_prev(values, W=5):
hW = (W-1)//2
maxv = maxf(values,W, origin=hW)
mask = values[1:] > maxv[:-1]
mask[:W-1] = 0
return np.flatnonzero(mask)+1
示例运行 -
In [336]: values
Out[336]:
array([160, 140, 152, 142, 143, 186, 152, 145, 165, 152, 143, 148, 196,
152, 145, 157, 152])
In [337]: greater_than_all_prev(values, W=5)
Out[337]: array([ 5, 12])
答案 1 :(得分:1)
Erik Rigtorp为Efficient rolling statistics with NumPy发布了一个很好的技巧:
与C代码中的循环相比,Python中的循环非常慢。 幸运的是,有一个技巧可以让NumPy执行这种循环 在C代码内部。这是通过添加额外的维度来实现的 与窗口大小相同,并有适当的步幅:
def rolling_window(a, window): shape = a.shape[:-1] + (a.shape[-1] - window + 1, window) strides = a.strides + (a.strides[-1],) return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
使用此功能可以:
winlen = 5
values = np.array([160, 140, 152, 142, 143, 186, 152, 145, 165, 152, 143, 148, 196, 152, 145, 157, 152])
rolling_values = rolling_window(values, winlen + 1)
rolling_indices = np.arange(winlen, values.shape[0])
mask = np.all(rolling_values[:, [-1]] > rolling_values[:, :-1], axis=1)
indices = rolling_indices[mask]
print(indices)
rolling_window
将值转换为以下格式的数组:
print(rolling_values)
array([[160, 140, 152, 142, 143, 186],
[140, 152, 142, 143, 186, 152],
[152, 142, 143, 186, 152, 145],
[142, 143, 186, 152, 145, 165],
[143, 186, 152, 145, 165, 152],
[186, 152, 145, 165, 152, 143],
[152, 145, 165, 152, 143, 148],
[145, 165, 152, 143, 148, 196],
[165, 152, 143, 148, 196, 152],
[152, 143, 148, 196, 152, 145],
[143, 148, 196, 152, 145, 157],
[148, 196, 152, 145, 157, 152]])
每行包含一个元素(从第六个开始)和前五个元素。由于步幅技巧,这种表示不需要比原始数组更多的内存。
现在,我们可以比较每行中的最后一个元素是否大于previos元素,并查找相应的索引。
答案 2 :(得分:0)
一个简单的方法是:
@Value
如果您在某个索引处的import numpy as np
values = np.array([160, 140, 152, 142, 143, 186, 152, 145, 165, 152, 143, 148, 196, 152, 145, 157, 152])
prod = np.ones_like(values)
for n in range(1,6):
prod *= values > np.roll(values, n)
print(prod)
中找到1
,那么在prod
的此索引处,您的条件将大于前五个元素。您可以使用values
找到这些索引。您应该注意np.where(prod == 1)
包围数组的边界。