【问题标题】:Get the indices of N highest values in an ndarray获取 ndarray 中 N 个最高值的索引
【发布时间】:2014-12-23 14:05:18
【问题描述】:

考虑到形状为 100x100x100 的直方图,我想找到 2 个最高值 a 和 b,以及它们的索引 (a1, a2, a3) 和 (b1, b2, b3),例如:

hist[a1][a2][a3] = a
hist[b1][b2][b3] = b

我们可以很容易地用 hist.max() 得到最大值,但是我们怎样才能得到一个 ndarray 中的 X 个最大值呢?

我知道人们通常使用 np.argmax 来检索值索引,但在这种情况下:

hist.argmax().shape = ()  # single value
for i in range(3):
    hist.argmax(i).shape = (100, 100)

我怎样才能得到一个形状 (3),一个每个维度有一个值的元组?

【问题讨论】:

    标签: python numpy indexing multidimensional-array


    【解决方案1】:

    我想你可以这样做:

    (伪代码)

    #work on a copy
    working_hist = copy(hist)
    greatest = []
    
    min_value = hist.argmin().shape
    
    #while searching for the N greatest values, do N times
    for i in range(N):
        #get the current max value
        max_value = hist.argmax().shape
        #save it
        greatest.append(max_value)
        #and then replace it by the minimum value
        hist(max_value.shape)= min_value
    

    多年来我没有使用过 numpy,所以我不确定语法。代码只是为了给你一个类似答案的伪代码。

    如果您还保留提取的值的位置,则可以通过使用提取的信息在最后恢复矩阵来避免处理项目的副本。

    【讨论】:

      【解决方案2】:

      你可以使用where:

      a=np.random.random((100,100,100))
      np.where(a==a.max())
      (array([46]), array([62]), array([61]))
      

      进入单个数组:

      np.hstack(np.where(a==a.max()))
      array([46, 62, 61])
      

      并且,正如 OP 要求的元组:

      tuple(np.hstack(np.where(a==a.max())))
      (46, 62, 61)
      

      编辑:

      要获取N 最大集合的索引,您可以使用heapq 模块中的nlargest 函数:

      N=3
      np.where(a>=heapq.nlargest(3,a.flatten())[-1])
      (array([46, 62, 61]), array([95, 85, 97]), array([70, 35,  2]))
      

      【讨论】:

      • 谢谢!我写了一个benchmark test,显示argpartition方法比where快22倍。感谢提供这个例子,从中学到了很多!
      【解决方案3】:

      您可以首先在扁平化版本的数组上使用numpy.argpartition 来获取顶部k 项目的索引,然后您可以使用numpy.unravel_index 根据数组的形状转换这些一维索引:

      >>> arr = np.arange(100*100*100).reshape(100, 100, 100)
      >>> np.random.shuffle(arr)
      >>> indices =  np.argpartition(arr.flatten(), -2)[-2:]
      >>> np.vstack(np.unravel_index(indices, arr.shape)).T
      array([[97, 99, 98],
             [97, 99, 99]])
      )
      >>> arr[97][99][98]
      999998
      >>> arr[97][99][99]
      999999
      

      【讨论】:

      • 谢谢,我不知道如何正确使用 argpartition 和 unravel_index,现在很有意义。接受了你的答案,但如果@atomh33ls 更新了他的答案,我将对这两个解决方案进行基准测试:)
      • Benchmark test: argpartition 很快 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      • 2018-02-16
      • 2021-08-06
      • 2022-06-13
      • 2015-04-09
      • 2015-07-31
      • 1970-01-01
      相关资源
      最近更新 更多