Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
207 views
in Technique[技术] by (71.8m points)

python - Numpy - how to sort an array of value/key pairs in descending order

I was looking at the problem Fastest way to rank items with multiple values and weightings and came up with the following solution, but with two remaining issues:

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?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could merge res and keys into a structured array:

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

Since np.sort does not have a reverse=True flag, I think the best you can do is reverse the returned array, (e.g. items[::-1]) or else take the negative of 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)

yields

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

Note that refunctions.merge_arrays is just a Python convenience function. It uses zip and np.fromiter. It would definitely be faster to avoid joining res and keys and instead use argsort to find the indices that sort res and use those to reorder 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])

yields

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...