这基本上是image closing operation in image-processing
针对一维案例的.这些操作可以用卷积方法实现.现在,NumPy does support 1D convolution
我们很幸运!因此,为了解决我们的情况,它会是这样的 -
def conv_app(A, WSZ): K = np.ones(WSZ,dtype=int) L = WSZ-1 return (np.convolve(np.convolve(A,K)>=WSZ,K)[L:-L]>0).astype(int)
样品运行 -
In [581]: A Out[581]: array([1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1]) In [582]: conv_app(A,4) Out[582]: array([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]) In [583]: A = np.append(1,A) # Append 1 and see what happens! In [584]: A Out[584]: array([1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1]) In [585]: conv_app(A,4) Out[585]: array([1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1])
运行时测试 -
本节将对列出的其他方法进行基准测试,以解决已发布的问题.他们的定义如下 -
def groupby_app(A,WSZ): # @lambo477's solution groups = itertools.groupby(A) result = [] for group in groups: group_items = [item for item in group[1]] group_length = len(group_items) if group_length >= WSZ: result.extend([item for item in group_items]) else: result.extend([0]*group_length) return result def stride_tricks_app(arr, window): # @ajcr's solution x = pd.rolling_min(arr, window) x[:window-1] = 0 y = np.lib.stride_tricks.as_strided(x, (len(x)-window+1, window), (8, 8)) y[y[:, -1] == 1] = 1 return x.astype(int)
计时 -
In [541]: A = np.random.randint(0,2,(100000)) In [542]: WSZ = 4 In [543]: %timeit groupby_app(A,WSZ) 10 loops, best of 3: 74.5 ms per loop In [544]: %timeit stride_tricks_app(A,WSZ) 100 loops, best of 3: 3.35 ms per loop In [545]: %timeit conv_app(A,WSZ) 100 loops, best of 3: 2.82 ms per loop