Rank array of tuples
I have an array
array = [('item1',90),('item2',76),('item3',83),('item4',90)]
and I would like to rate it as
ranking = [(0,'item1'),(0,'item4'),(2,'item3'),(3,'item2')] // (1)
This is what I have done so far using ranking :
from ranking import *
>>> array.sort(key=lambda x: x[1],reverse = True)
>>> print [i for i in list(Ranking([i[1] for i in array]))]
This is what I get:
[(0, 90), (0, 90), (2, 83), (3, 76)] // (2)
Can anyone help me get from (2) to (1)? I don't need to use ranking
. I accept any other decision.
source to share
array = [('item1',90),('item2',76),('item3',83),('item4',90)]
srt = sorted(array,key=lambda x: x[1], reverse=True)
rankings = []
rank = 0
from itertools import groupby
for k,v in groupby(srt,lambda x: x[1]): # group by score
grp = [(rank,tup[0]) for tup in v] # get item tup[0] and put it in a tuple with the rank
rankings += grp
rank += len(grp) # increase rank for next grouping
print(rankings)
[(0, 'item1'), (0, 'item4'), (2, 'item3'), (3, 'item2')]
source to share
array = [('item1',90),('item2',76),('item3',83),('item4',90)]
def s(t):
return t[1]
array.sort(reverse = True, key = s)
def rank(array):
res = []
for index, tup in enumerate(array):
if index == 0:
res.append(tuple([ index, tup[0]]))
elif tup[1] == array[index -1][1]:
res.append(tuple([index -1, tup[0]]))
else:
res.append(tuple([index , tup[0]]))
return res
r = rank(array)
print r
Output - [(0, 'item1'), (0, 'item4'), (2, 'item3'), (3, 'item2')]
This can be a very long solution, but I hope it works fine
source to share
You can use Pandas DataFrame for this. I would recommend this solution as it is very semantically intended for the purposes you want to put it for:
import pandas as pd
df = pd.DataFrame.from_records([('item1',90),('item2',76),
('item3',83),('item4',90)])
Here's the raw dataframe before we process it:
>>> df
0 1
0 item1 90
1 item2 76
2 item3 83
3 item4 90
Now we will select column 1 and break it down in descending order, and then add the rank back to the framework (using the min method):
>>> df['rank'] = df[1].rank(method='min', ascending=False)
>>> df
0 1 rank
0 item1 90 1
1 item2 76 4
2 item3 83 3
3 item4 90 1
We now convert our lookup columns back to a list of tuples excluding the index:
>>> l = list(df[[0, 'rank']].to_records(index=False))
>>> l
[('item1', 1.0), ('item2', 4.0), ('item3', 3.0), ('item4', 1.0)]
We can get it into the desired state with a list:
>>> l2 = [(i, int(j-1)) for i, j in l]
>>> l2
[('item1', 0), ('item2', 3), ('item3', 2), ('item4', 0)]
source to share
I don't have a ranking so I can't test it, but the documentation says Ranking () supports passing a key function to select values ββfrom a list.
I suggest trying something like this:
print Ranking(array, key=lambda x: x[1], reverse=True)
source to share
array = [('item1',90),('item2',76),('item3',83),('item4',90)]
values = sorted(v for k, v in array)
d = dict(zip(values, range(len(values)-1, -1, -1)))
print sorted(( (d[i],item) for (item, i) in array ))
This results in the output:
[(0, 'item1'), (0, 'item4'), (2, 'item3'), (3, 'item2')]
How it works
values
contains a sorted list of values:
[76, 83, 90, 90]
We then create a dictionary d
to rank their order. d
:
{76: 3, 83: 2, 90: 0}
source to share