【问题标题】:Numpy: advanced slicesNumpy:高级切片
【发布时间】:2016-12-28 02:58:24
【问题描述】:

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

例如我有一个 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,这是我的项目)

【问题讨论】:

  • 看起来您正在尝试对具有许多行的整个二维数组执行此操作。您真的需要 all 值,还是只需要最后一行,或者只需要最后一行中的一个值?在后一种情况下,您可能可以使用一些更专业的算法。
  • @david-z 我处理大图像,我计算了一些能量,将它们转换为 YUV。是的,我需要计算每个值,找到最后一行的最小值!重要的是要在整个图像中找到接缝,我将删除它以智能地调整图像大小。

标签: python arrays performance numpy slice


【解决方案1】:

使用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.]])

【讨论】:

  • 好吧,我解释的不够清楚!应该找到位于边界元素之间的元素,使用下面的三个邻居!对于元素matrix[h][w],我们需要检查matrix[h-1][w-1]、matrix[h-1][w]和matrix[h-1][w+1]!!跨度>
  • @Tehada:好吧,我解释的代码不够清楚。它取三个相邻元素w-1ww+1 中的最小值,但作为向量来消除另一个循环。
  • 非常感谢!现在,当我使用 2 个 for 循环时,它只需要 0.02 秒而不是 1.3 秒!现在我正在考虑一项改进:我有一个带有 int 值的大型 2D 表,我想在没有任何 for 循环的情况下解决这个问题。
【解决方案2】:

我会明确地这样做,以便通过显式切片更加清晰

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]

【讨论】:

    【解决方案3】:

    以下是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 行矩阵(丹尼尔解决方案的核心):

    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])]
    

    axis=0 上的np.min 等效于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])
    

    =========

    将此扩展到二维数组:

    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]])
    

    【讨论】:

    • 嗯,这个解决方案很漂亮,很清晰,我会学习这个!但它在大数据上速度很快吗?
    猜你喜欢
    • 1970-01-01
    • 2019-06-16
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多