Skip to content Skip to sidebar Skip to footer

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 n

Solution 1:

You could merge res and keys into a structured array:

import numpy.lib.recfunctions as recfunctionsitems= 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 valueskeys = 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 valueskeys = 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.]

Solution 2:

You can use argsort method of numpy arrays to sort keys with indices that would sort other array.

import numpy as np

# set up valueskeys = 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]]

Solution 3:

With thanks to @ondro and @unutbu, here is what I finally ended up with:

import numpy as np

# set up valueskeys = 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()

which returns ['key3', 'key2', 'key1'] (keys, sorted in reverse order by dot-product of values and weights).

Post a Comment for "Numpy - How To Sort An Array Of Value/key Pairs In Descending Order"