Numpy - 如何按降序排序值/键对数组
我在研究一个问题,链接在这里:如何快速对多个值和权重的项目进行排名。我想出了一个解决方案,但还有两个问题没有解决:
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
感谢@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']
(这些是键,按照值和权重的点积反向排序的)。
2
你可以把 res
和 keys
合并成一个结构化的数组:
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 函数。它使用了 zip
和 np.fromiter
。如果能避免把 res
和 keys
合并,而是用 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.]
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]]