【问题标题】:Numpy - how to sort an array of value/key pairs in descending orderNumpy - 如何按降序对值/键对数组进行排序
【发布时间】:2014-03-02 01:46:34
【问题描述】:

我正在查看问题Fastest way to rank items with multiple values and weightings 并提出以下解决方案,但还有两个问题:

import numpy as np

# set up values
keys = np.array([
    ['key1'],
    ['key2'],
    ['key3']
])
values = np.matrix([
    [1.1, 1.2, 1.3, 1.4],
    [2.1, 2.2, 2.3, 2.4],
    [3.1, 3.2, 3.3, 3.4]
])
weights = np.matrix([10., 20., 30., 40.]).transpose()

# crunch the numbers
res = values * weights

# combine results with labels
items = np.hstack((np.array(res), keys))

# !First problem - .hstack has promoted the first column from float64 to S4:
# array([['130.', 'key1'],
#        ['230.', 'key2'],
#        ['330.', 'key3']], 
#       dtype='|S4')
# How can I force it to stay numeric?

items.sort(reverse=True)   # doesn't work, no 'reverse' argument

# !Second problem - how to sort the array in descending order?

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    您可以将reskeys 合并为一个结构化数组:

    import numpy.lib.recfunctions as recfunctions
    items = recfunctions.merge_arrays([res,keys])
    

    由于np.sort 没有reverse=True 标志,我认为你能做的最好的就是反转返回的数组,(例如items[::-1])或者取res 的负数:

    import numpy as np
    import numpy.lib.recfunctions as recfunctions
    
    # set up values
    keys = np.array([
        ['key1'],
        ['key2'],
        ['key3']
    ])
    values = np.matrix([
        [1.1, 1.2, 1.3, 1.4],
        [2.1, 2.2, 2.3, 2.4],
        [3.1, 3.2, 3.3, 3.4]
    ])
    weights = np.matrix([10., 20., 30., 40.]).transpose()
    
    # crunch the numbers
    res = values * weights
    
    # combine results with labels
    res = np.asarray(-res)
    items = recfunctions.merge_arrays([res,keys])
    items.dtype.names = ['res', 'key']
    items.sort(order=['res'])
    print(items)
    

    产量

    [(-330.0, 'key3') (-230.0, 'key2') (-130.0, 'key1')]
    

    请注意,refunctions.merge_arrays 只是一个 Python 便利函数。它使用zipnp.fromiter。避免加入reskeys 并使用argsort 查找排序res 的索引并使用这些索引重新排序keys 肯定会更快:

    import numpy as np
    
    # set up values
    keys = np.array([
        ['key1'],
        ['key2'],
        ['key3']
    ])
    values = np.matrix([
        [1.1, 1.2, 1.3, 1.4],
        [2.1, 2.2, 2.3, 2.4],
        [3.1, 3.2, 3.3, 3.4]
    ])
    weights = np.matrix([10., 20., 30., 40.]).transpose()
    
    # crunch the numbers
    res = values * weights
    
    # combine results with labels
    res = np.squeeze(np.asarray(res))
    idx = np.argsort(res)[::-1]
    print(keys[idx])
    print(res[idx])
    

    产量

    [['key3']
     ['key2']
     ['key1']]
    [ 330.  230.  130.]
    

    【讨论】:

      【解决方案2】:

      您可以使用 numpy 数组的 argsort 方法对具有索引的键进行排序,从而对其他数组进行排序。

      import numpy as np
      
      # set up values
      keys = np.array([
          ['key1'],
          ['key2'],
          ['key3']
      ])
      values = np.array([
          [1.1, 1.2, 1.3, 1.4],
          [2.1, 2.2, 2.3, 2.4],
          [3.1, 3.2, 3.3, 3.4]
      ])
      weights = np.array([10., 20., 30., 40.])
      
      # crunch the numbers
      res = np.dot(values, weights)
      
      sortedkeys = keys[res.argsort(axis=0)[::-1]]
      

      【讨论】:

        【解决方案3】:

        感谢@ondro 和@unutbu,这就是我最终得到的结果:

        import numpy as np
        
        # set up values
        keys = np.array(['key1', 'key2', 'key3'])
        values = np.array([
            [1.1, 1.2, 1.3, 1.4],    # values1_x
            [2.1, 2.2, 2.3, 2.4],    # values2_x
            [3.1, 3.2, 3.3, 3.4]     # values3_x
        ])
        weights = np.array([10., 20., 30., 40.])
        
        # crunch the numbers
        res = np.dot(values, -weights)   # negative of weights!
        
        order = res.argsort(axis=0)  # sorting on negative value gives
                                     # same order as reverse-sort; there does
                                     # not seem to be any way to reverse-sort
                                     # directly
        sortedkeys = keys[order].tolist()
        

        返回['key3', 'key2', 'key1'](键,按值和权重的点积倒序排序)。

        【讨论】:

          最近更新 更多