【问题标题】:Fastest way to get (i,j) indices of a value in a Python matrix array?获取Python矩阵数组中值的(i,j)索引的最快方法?
【发布时间】:2020-07-07 01:11:43
【问题描述】:

在下面的 numpy 数组中获取值 1 的所有 (i,j) 索引的最快方法是什么?

import numpy as np 

arr = [[1, 0, 1], [0, 0, 0], [0, 1, 0]]
arr = np.array(arr)
arr
array([[1, 0, 1],
       [0, 0, 0],
       [0, 1, 0]])

我尝试过使用嵌套的 for 循环 for i for j,但对于较大的数据集,这需要 O(n^2)。我也尝试过使用np.where(arr == 1),但没有得到 (i,j) 索引:

np.where(arr == 1)
(array([0, 0, 2]), array([0, 2, 1])) # not (i,j) indices

获取 (i,j) 索引的更好或更快的方法是什么?

【问题讨论】:

  • where 给出索引 - 作为数组的元组。这确实是最有用的形式,因为它可以直接用于索引数组。必须一个一个地应用一个元组列表,速度要慢得多。

标签: python arrays numpy matrix


【解决方案1】:

您返回的两个数组只是每个匹配项的列/行索引。您可以简单地将第一个和第二个数组一起压缩成元组。

import numpy as np 

arr = [[1, 0, 1], [0, 0, 0], [0, 1, 0]]
arr = np.array(arr)    

d = np.where(arr == 1)
tuple(zip(d[0], d[1]))

输出

((0, 0), (0, 2), (2, 1))

【讨论】:

  • 没问题欢迎采纳,让其他人受益。
  • np.where 是否在底层使用嵌套的for i for j for 循环?或者它使用某种形式的更快的搜索,比如二分搜索?尝试查看源代码,但无法弄清楚... @Chris
  • np.nonzeros 只是遍历 while 数组(展平)寻找 True 值。没什么特别的,只是编译。
【解决方案2】:

如果您坚持将索引设置为 i-j 对,请使用 np.argwhere

ij = np.argwhere(arr == 1)

ij 将是一个 Nx2 数组,每行包含一个索引对。您仍然可以将这些列用作精美的索引。

否则,请使用 np.nonzero,当您使用单个参数执行 np.where 时会调用它:

i, j = np.nonzero(arr)

如果您的数组严格为零或一,则在任何一种情况下都不需要== 0。这两个函数都查找非零元素。

另外,请记住,所有这些函数都具有相似的时间复杂度,即O(N),因为N 是数组中元素的总数。无论您使用 numpy 函数还是嵌套的 for 循环,都需要对数组进行至少一次传递。

【讨论】:

    【解决方案3】:

    所以这基本上是一个简单的数组遍历问题,这个问题总是需要 O(n^2) 时间。

    所以我觉得这里可以使用循环

    输入:

    arr = [[1, 0, 1], [0, 0, 0], [0, 1, 0]]
    arr = np.array(arr)
    
    
    def method_1(arr):
        temp = []
        for i in range(len(arr)):
            for j in range(len(arr[i])):
                if arr[i][j] == 1:
                    temp.append((i, j))
        return temp
    
    
    def method_2(arr):
        d= np.where(arr == 1)
        temp = []
        for i, j in zip(d[0], d[1]):
            temp.append((i, j))
        return temp
    
    
    start_time = time.time()
    method_1(arr)
    end_time = time.time()
    
    print(end_time- start_time)
    
    start_time = time.time()
    method_2(arr)
    end_time = time.time()
    
    print(end_time- start_time)
    
    

    输出:

    2.00271606445e-05          #Time taken by 1st algorithm
    4.50611114502e-05          #Time taken by 2nd algorithm
    [(0, 0), (0, 2), (2, 1)]
    [(0, 0), (0, 2), (2, 1)]
    
    

    注意:当你想检查算法的效率时,你可以使用时间函数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-03
      • 1970-01-01
      • 2021-12-11
      • 2014-07-12
      • 2016-11-13
      • 2011-11-12
      • 1970-01-01
      相关资源
      最近更新 更多