Numpy - 如何按降序对值/键对数组进行排序

时间:2014-03-02 01:46:34

标签: python arrays numpy

我正在查看问题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?

3 个答案:

答案 0 :(得分:2)

您可以将reskeys合并到结构化数组中:

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

由于np.sort没有reverse=True标志,我认为您可以做的最好的事情是反转返回的数组(例如items[::-1])或者取消{{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')] 只是一个Python便利功能。它使用refunctions.merge_arrayszip。避免加入np.fromiterres肯定会更快,而是使用keys查找排序argsort的索引并使用这些索引重新排序res:< / p>

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])

答案 1 :(得分:1)

您可以使用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]]

答案 2 :(得分:0)

感谢@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'](键,按值和重量的点积按相反的顺序排序)。