【问题标题】:list of indexes of maximum values in ndarrayndarray 中最大值的索引列表
【发布时间】:2013-02-27 23:08:44
【问题描述】:

我有一个 ndarray。从这个数组中,我需要选择具有最大值的 N 个数字的列表。我找到heapq.nlargest 找到了N 个最大的条目,但我需要提取索引。 我想构建一个新数组,其中只有第一列中权重最大的 N 行才能存活。其余行将被随机值替换

import numpy as np
import heapq   # For choosing list of max values
a = [[1.1,2.1,3.1], [2.1,3.1,4.1], [5.1,0.1,7.1],[0.1,1.1,1.1],[4.1,3.1,9.1]]
a = np.asarray(a)
maxVal = heapq.nlargest(2,a[:,0])

if __name__ == '__main__':
    print a
    print maxVal

我的输出是:

[[ 1.1  2.1  3.1]
[ 2.1  3.1  4.1]
[ 5.1  0.1  7.1]
[ 0.1  1.1  1.1]
[ 4.1  3.1  9.1]]

[5.0999999999999996, 4.0999999999999996]

但我需要[2,4] 作为索引来构建一个新数组。索引是行,所以如果在这个例子中我想用 0 替换其余部分,我需要完成:

[[0.0  0.0  0.0]
[ 0.0  0.0  0.0]
[ 5.1  0.1  7.1]
[ 0.0  0.0  0.0]
[ 4.1  3.1  9.1]]

我被困在需要索引的地方。原始数组有 1000 行和 100 列。权重是归一化的浮点数,我不想做类似if a[:,1] == maxVal[0]: 这样的事情,因为有时我的权重非常接近,并且可以以比我原来的 N 更多的值结束 maxVal[0]

是否有任何简单的方法可以在此设置中提取索引以替换数组的其余部分?

【问题讨论】:

    标签: python numpy indexing


    【解决方案1】:

    如果你只有 1000 行,我会忘记堆并在第一列使用np.argsort

    >>> np.argsort(a[:,0])[::-1][:2]
    array([2, 4])
    

    如果你想把它们放在一起,它看起来像:

    def trim_rows(a, n) :
        idx = np.argsort(a[:,0])[:-n]
        a[idx] = 0
    
    >>> a = np.random.rand(10, 4)
    >>> a
    
    array([[ 0.34416425,  0.89021968,  0.06260404,  0.0218131 ],
           [ 0.72344948,  0.79637177,  0.70029863,  0.20096129],
           [ 0.27772833,  0.05372373,  0.00372941,  0.18454153],
           [ 0.09124461,  0.38676351,  0.98478492,  0.72986697],
           [ 0.84789887,  0.69171688,  0.97718206,  0.64019977],
           [ 0.27597241,  0.26705301,  0.62124467,  0.43337711],
           [ 0.79455424,  0.37024814,  0.93549275,  0.01130491],
           [ 0.95113795,  0.32306471,  0.47548887,  0.20429272],
           [ 0.3943888 ,  0.61586129,  0.02776393,  0.2560126 ],
           [ 0.5934556 ,  0.23093912,  0.12550062,  0.58542137]])
    >>> trim_rows(a, 3)
    >>> a
    
    array([[ 0.        ,  0.        ,  0.        ,  0.        ],
           [ 0.        ,  0.        ,  0.        ,  0.        ],
           [ 0.        ,  0.        ,  0.        ,  0.        ],
           [ 0.        ,  0.        ,  0.        ,  0.        ],
           [ 0.84789887,  0.69171688,  0.97718206,  0.64019977],
           [ 0.        ,  0.        ,  0.        ,  0.        ],
           [ 0.79455424,  0.37024814,  0.93549275,  0.01130491],
           [ 0.95113795,  0.32306471,  0.47548887,  0.20429272],
           [ 0.        ,  0.        ,  0.        ,  0.        ],
           [ 0.        ,  0.        ,  0.        ,  0.        ]])
    

    对于您的数据大小,它可能已经足够快了:

    In [7]: a = np.random.rand(1000, 100)
    
    In [8]: %timeit -n1 -r1 trim_rows(a, 50)
    1 loops, best of 1: 7.65 ms per loop
    

    【讨论】:

    • 首先检索N 最后一个数字然后反转它们可能成本更低,而不是反转整个列表。类似np.argsort(a[:,0])[-2:][::-1]
    • @entropy 它们基本上都是零成本操作,因为不会发生实际的数据混洗,只是移动步幅、形状和指针。使用a = np.arange(10**6) 我得到了这些时间:In [23]: %timeit a[-2:][::-1] 1000000 loops, best of 3: 740 ns per loopIn [24]: %timeit a[::-1][:2] 1000000 loops, best of 3: 731 ns per loop
    • 你可能是对的,我不知道python的列表实现是如何工作的。如果确实它实际上并没有反转底层数组,只需更改步幅和开始/结束指针,那么你是绝对正确的
    • @entropy Python 列表确实有与反转它们相关的成本,然后你的观察是正确的。再次使用 a = range(10**6) 这些是时间安排:In [26]: %timeit a[::-1][:2] 100 loops, best of 3: 9.54 ms per loopIn [27]: %timeit a[-2:][::-1] 1000000 loops, best of 3: 333 ns per loop 所以你的方法然后是 x30,000 倍快。它只是不适用于 numpy 数组。
    • 啊,我错过了 np.argsort() 返回一个 numpy 数组的事实。我的坏:)
    猜你喜欢
    • 2015-10-24
    • 2012-07-16
    • 1970-01-01
    • 2014-12-23
    • 2021-08-06
    • 2019-02-17
    • 1970-01-01
    • 2022-01-05
    • 2023-03-29
    相关资源
    最近更新 更多