【问题标题】:Fastest iteration over 2 dimensions in pythonpython中二维上最快的迭代
【发布时间】:2020-07-14 19:08:48
【问题描述】:

在 python 中迭代二维数组的最快方法是什么?考虑到我总是需要 x 和 y 索引。

例如,我有这段代码试图“匹配”矩阵中相同数字的 3 个,如果它们是数字 2、3、4、5 或 6:

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 i find one of the numbers i need
            fuseNumber = matrix[x][y] ## lets get that number
            if matrix[x+1][y] == fuseNumber: ## if we find another of that to the bottom of the initial one, we should try to find a third one
                if matrix[x-1][y] == fuseNumber: ## if we find another one at the top from the initial one
                    matrix[x][y] = 0
                    matrix[x+1][y] = 0
                    matrix[x-1][y] = 0
                    ...

代码将继续使用一些 if,就像这个一样,以确保它测试所有可能的组合,但这并不重要。 我尝试将其更改为:

it = numpy.nditer(matrix, flags=['multi_index'])
while not it.finished:
    x = it.multi_index[0]
    y = it.multi_index[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:
        fuseNumber = matrix[x][y] ## lets get that fuse number, whichever it may be!
        if matrix[x+1][y] == fuseNumber: ## if we find another of that to the bottom of the initial one, we should try to find a third one
            if matrix[x-1][y] == fuseNumber: ## if we find another one at the top from the initial one  ///////  center bottom top
                matrix[x][y] = 0
                matrix[x+1][y] = 0
                matrix[x-1][y] = 0
                ...
it.iternext()

但是使用 timeit.timeit() 它向我展示了第二个代码实际上更慢。尽管有这两个示例,但您将如何编写相同的代码,但获得最佳性能?

谢谢!

【问题讨论】:

  • nditer 不是更快的迭代器,至少在 Python 级别使用时不是。只有在编译代码中使用它才有帮助。在 Python 代码中没有更快的方法来迭代数组。在列表上迭代更快。要获得最佳的numpy 速度,您应该使用快速编译的numpy 方法,而不是迭代。
  • 您上一个问题的答案有什么问题? stackoverflow.com/questions/60993647/…。我很想将此标记为重复。
  • @hpaulj 没什么,真的,这只是一个不同的问题,因为现在我需要更多地控制索引,它实际上是另一种方法,但我承认这个问题看起来一样哈哈

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


【解决方案1】:

而不是使用双 for 循环进行搜索:

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 i find one of the numbers i need
            fuseNumber = matrix[x][y] ## lets get that fuse number,
         ...

您可以使用 where 搜索 example

这允许仅在所需范围内的 x、y 值上循环。

for x, y in zip(*np.where(np.logical_and(matrix>=2, matrix<=6))):
    fuseNumber = matrix[x][y] ## lets get that fuse number,
         ...

测试

测试这两种方法是否创建相同的 x,y 对

# Random matrix (5, 10) with numbers between 0 & 10
matrix = np.random.randint(0, 10,  size=(5, 10))

# OP method
set_for = set()
for x in range(matrix.shape[0]):
    for y in range(matrix.shape[1]):
      if 2 <= matrix[x][y] <= 6:
        set_for.add((x, y))

# Method using where
set_numpy = set((x, y) for x, y in zip(*np.where(np.logical_and(matrix>=2, matrix<=6))))

# Result
print(set_for == set_numpy)

输出

True

【讨论】:

  • 我这样做了,它确实更快,但它没有做同样的事情,我的程序有点停止做它应该做的事情,我还没有意识到问题是什么,但明天会调查。你有什么见解吗?也许我应该做 'for y, x' 而不是 'for x, y' ?谢谢!
  • @LaioZatt--x, y 应该对应于你所拥有的行、列对。也许您可以尝试将此方法找到的 x, y 对放入一个集合中,以与双 for 循环方法找到的 x, y 对进行比较。然后检查两组是否相等。
  • @LaioZatt--添加了一个简单的测试(见更新),新方法产生与原始方法相同的 x、y 对。
  • 谢谢,虽然我对如何将这条线应用于我的问题仍然有点困惑。我在哪里使用它,例如fuseNumber = matrix[x][y] ## lets get that number if matrix[x+1][y] == fuseNumber: ## if we find another of that to the bottom of the initial one, we should try to find a third one if matrix[x-1][y] == fuseNumber: ## if we find another one at the top from the initial one matrix[x][y] = 0 matrix[x+1][y] = 0 matrix[x-1][y] = 0 你将如何使用这种语法?我还是个新手=P。再次感谢
  • @LaioZatt--如果 x, y 通过你的两个外部循环,那么我们知道2 &lt;= matrix[x][y] &lt;= 6。所以我们只需要考虑这些 x, y 对。对于这些 x,y 对,您检查 matrix[x+1][y] = matrix[x][y]matrix[x-1][[y] = matrix[x][y](您正在设置 fusenumber = matrix[x][y] 进行比较,但您可以使用 matrix[x][y] 而不是 fusenumber。可能的问题是不检查是否0 &lt; x &lt; len(matrix[0]) - 1]。这需要检查,因为如果x = 0,然后matrix[x-1] would be an index out of range error. Similar error if 'x &gt;= len(matrix[0]) -1
猜你喜欢
  • 2020-07-14
  • 2023-02-06
  • 2020-07-15
  • 2011-12-28
  • 2015-04-04
  • 2013-11-16
  • 1970-01-01
  • 2013-05-09
  • 2018-08-01
相关资源
最近更新 更多