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?
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.]