【问题标题】:How to faster iterate over a Python numpy.ndarray with 2 dimensions如何更快地迭代二维的 Python numpy.ndarray
【发布时间】:2020-07-14 13:06:48
【问题描述】:

所以,我只是想让这更快:

for x in range(matrix.shape[0]):
        for y in range(matrix.shape[1]):
            if matrix[x][y] == 2 or matrix[x][y] == 3 or matrix[x][y] == 4 or matrix[x][y] == 5 or matrix[x][y] == 6:
                if x not in heights:
                    heights.append(x)

只需遍历一个 2x2 矩阵(通常为 18x18 或 22x22 圆形)并检查它是否为 x。但它有点慢,我想知道哪种方法最快。

非常感谢!

【问题讨论】:

    标签: python python-3.x numpy multidimensional-array numpy-ndarray


    【解决方案1】:

    对于基于 numpy 的方法,您可以这样做:

    np.flatnonzero(((a>=2) & (a<=6)).any(1))
    # array([1, 2, 6], dtype=int64)
    

    地点:

    a = np.random.randint(0,30,(7,7))
    
    print(a)
    
    array([[25, 27, 28, 21, 18,  7, 26],
           [ 2, 18, 21, 13, 27, 26,  2],
           [23, 27, 18,  7,  4,  6, 13],
           [25, 20, 19, 15,  8, 22,  0],
           [27, 23, 18, 22, 25, 17, 15],
           [19, 12, 12,  9, 29, 23, 21],
           [16, 27, 22, 23,  8,  3, 11]])
    

    更大数组的时序:

    a = np.random.randint(0,30, (1000,1000))
    
    %%timeit
    heights=[]
    for x in range(a.shape[0]):
            for y in range(a.shape[1]):
                if a[x][y] == 2 or a[x][y] == 3 or a[x][y] == 4 or a[x][y] == 5 or a[x][y] == 6:
                    if x not in heights:
                        heights.append(x)
    # 3.17 s ± 59.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    %%timeit
    yatu = np.flatnonzero(((a>=2) & (a<=6)).any(1))
    # 965 µs ± 11.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    np.allclose(yatu, heights)
    # true
    

    使用 numpy 进行向量化产生大约 3200x 加速

    【讨论】:

    • 还是有点困惑,你介意把它应用到我的问题上,这样我就可以看到它是如何工作的?谢谢!
    • 你还没有共享样本数据。我已经检查过了,这与您的代码完全相同。对于此示例数组,heights 是 [1,2,6] a @LaioZatt
    • 我明白了。我确实设法让它工作,但它似乎并没有更快,至少在做:findHeightsTime = time.time() heights = numpy.flatnonzero(((matrix&gt;=2) &amp; (matrix&lt;=6)).any(1)) heights = heights[::-1] print("findHeightsTime : " + str(time.time() - findHeightsTime))也许我做错了什么?再次感谢 =)
    • 当然可以。您需要检查更大的样本。添加时间@LaioZatt
    • 我没有设法让 '%%timeit' 工作,但我用 time.timeit() 进行了尝试,这段代码的运行速度比我使用的快 40 倍左右。测试中存在这种差异的任何原因?我在做: setup = ''' import numpy ''' code = ''' heights = numpy.flatnonzero(((matrix>=2) & (matrix
    【解决方案2】:

    您似乎想查找矩阵中是否出现 2、3、4、5 或 6。

    您可以使用np.isin() 创建一个真/假值矩阵,然后将其用作索引器:

    >>> arr = np.array([1,2,3,4,4,0]).reshape(2,3)
    >>> arr[np.isin(arr, [2,3,4,5,6])]
    array([2, 3, 4, 4])
    

    (可选)将其转换为纯 Python set(),以便更快地查找 in 并且没有重复。

    要获取数组中这些数字出现的位置,请使用argwhere

    >>> np.argwhere(np.isin(arr, [2,3,4,5,6]))
    array([[0, 1],
           [0, 2],
           [1, 0],
           [1, 1]])
    

    【讨论】:

    • 我想得到那个 2 或 3 或 4 或 5 或 6 的 X 位置,如果它出现在矩阵中。您的解决方案仍然有效吗?你介意把它应用到我的问题上吗?我是 Python 新手 =P。谢谢!
    猜你喜欢
    • 2020-07-14
    • 2018-08-01
    • 2012-05-16
    • 2021-07-09
    • 2011-12-28
    • 2015-04-04
    • 2014-05-30
    • 2014-03-26
    • 1970-01-01
    相关资源
    最近更新 更多