Numpy:高级切片

时间:2016-08-21 13:15:11

标签: python arrays performance numpy slice

我需要一种快速的方法来查找字符串中三个相邻元素中的最小元素,并将其添加到中心元素下的元素中。对于边框元素,只检查两个上层元素。

例如,我有一个numpy数组:

    [1, 2, 3, 4, 5], 
    [0, 0, 0, 0, 0]

我应该得到这个:

    [1, 2, 3, 4, 5], 
    [1, 1, 2, 3, 4]

我有这段代码:

for h in range(1, matrix.shape[0]):
    matrix[h][0] = min(matrix[h - 1][0], matrix[h - 1][1])
    matrix[h][1:-1] = ...(DONT KNOW, WHAT SHOULD BE HERE!!)
    matrix[h][-1] = min(matrix[h - 1][-2], matrix[h - 1][-1])

如何在不使用更多for循环的情况下对其进行计数,因为我有太多数据而且需要快速进行? Edit: David-z,这是我的项目)Seam carving

3 个答案:

答案 0 :(得分:2)

使用numpy.minimum.reduce

matrix[h][1:-1] = numpy.minimum.reduce([matrix[h-1][0:-2], matrix[h-1][1:-1], matrix[h-1][2:]])

例如:

>>> matrix = numpy.zeros((2,10))
>>> matrix[0, :] = numpy.random.randint(0,100,10)
>>> h = 1
>>> matrix[h][0] = matrix[h-1][:2].min()
>>> matrix[h][1:-1] = numpy.minimum.reduce([matrix[h-1][0:-2], matrix[h-1][1:-1], matrix[h-1][2:]])
>>> matrix[h][-1] = matrix[h-1][-2:].min()
>>> matrix
array([[ 10.,  40.,  90.,  13.,  21.,  58.,  64.,  56.,  34.,  69.],
       [ 10.,  10.,  13.,  13.,  13.,  21.,  56.,  34.,  34.,  34.]])

答案 1 :(得分:1)

我会明确地使用显式切片

来明确表达
n = 10
x = np.random.randint(0,100,n)
y = np.zeros_like(x,dtype=int)


for ind in range(n):
    if ind == 0:
        lo , hi = None , ind + 2
    elif ind >= n-2:
        lo , hi = ind - 1 , None
    else:
        lo , hi = ind - 1 , ind + 2
    y[ind] = np.min(x[lo:hi])

示例输出是

[21 74 95 96  6 96 78 74  6 92  5 32 72 64 30 13 72 59 19 26]
[21 21 74  6  6  6 74  6  6  5  5  5 32 30 13 13 13 19 19 19]

答案 2 :(得分:1)

以下Daniel's解决方案略有不同:

从行或值列表开始:

In [439]: z=[10,40,90,13,21,58,64,56,34,69]

复制第一个和最后一个值;我可以通过连接,索引或简单的pad来实现这一点(内部pad相当复杂,因为它非常复杂):

In [440]: z1=np.pad(z,(1,1),'edge')
In [441]: z1
Out[441]: array([10, 10, 40, 90, 13, 21, 58, 64, 56, 34, 69, 69])

现在制作3行矩阵(Daniel解决方案的核心):

In [443]: [z1[0:-2], z1[1:-1], z1[2:]]
Out[443]: 
[array([10, 10, 40, 90, 13, 21, 58, 64, 56, 34]),
 array([10, 40, 90, 13, 21, 58, 64, 56, 34, 69]),
 array([40, 90, 13, 21, 58, 64, 56, 34, 69, 69])]
np.min上的

axis=0相当于minimum.reduce

In [444]: np.min([z1[0:-2], z1[1:-1], z1[2:]],axis=0)
Out[444]: array([10, 10, 13, 13, 13, 21, 56, 34, 34, 34])

======

将其扩展为2d数组:

In [454]: y=np.array(z).reshape(2,5)        # same values, reshape
In [455]: y1=np.pad(y,((0,0),(1,1)),'edge')  # 2d pad
In [456]: y1
Out[456]: 
array([[10, 10, 40, 90, 13, 21, 21],
       [58, 58, 64, 56, 34, 69, 69]])
In [457]: Y=np.array([y1[:,0:-2], y1[:,1:-1], y1[:,2:]])
In [458]: Y                            # 3d array
Out[458]: 
array([[[10, 10, 40, 90, 13],
        [58, 58, 64, 56, 34]],

       [[10, 40, 90, 13, 21],
        [58, 64, 56, 34, 69]],

       [[40, 90, 13, 21, 21],
        [64, 56, 34, 69, 69]]])
In [459]: np.min(Y,axis=0)
Out[459]: 
array([[10, 10, 13, 13, 13],
       [58, 56, 34, 34, 34]])

===============

as_strided替代方案(仅限高级numpy用户:))

In [462]: np.lib.stride_tricks.as_strided(z1,shape=(10,3),strides=(4,4)).T
Out[462]: 
array([[10, 10, 40, 90, 13, 21, 58, 64, 56, 34],
       [10, 40, 90, 13, 21, 58, 64, 56, 34, 69],
       [40, 90, 13, 21, 58, 64, 56, 34, 69, 69]])