Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort list by frequency and by value in Python

I have a list of numbers say, [2,2,3,3,4,1] I want to sort by frequency and if the frequency count (ascending) is same then sort by value (also ascending). Soln would be [1,4,2,2,3,3]

For frequency

from collections import Counter
print sorted(arr, key=Counter(arr).get)

But I am not sure how to sort by value for same frequency count elements

like image 655
Perseus14 Avatar asked Feb 23 '26 18:02

Perseus14


2 Answers

To follow up on @bro-grammer's comment (I used a tuple for the keys and called Counter only once):

There's this method which first has to go through the list for counting and then some more for sorting.

from collections import Counter
def perseus_sort(l):
    counter = Counter(l)
    return sorted(l, key=lambda x: (counter[x], x))

There's probably some clever algorithm that can somehow combine both of these but my intuition that it would be pretty complicated and more than you need

like image 110
Omer Tuchfeld Avatar answered Feb 25 '26 07:02

Omer Tuchfeld


This is one way via numpy.unique and numpy.lexsort:

import numpy as np

arr = np.array([2,2,3,3,4,1])

c = dict(zip(*np.unique(arr, return_counts=True)))

res = arr[np.lexsort((arr, list(map(c.get, arr))))]

# array([1, 4, 2, 2, 3, 3])

Some benchmarking below for a large array:

from collections import Counter
import numpy as np

arr = np.random.randint(0, 9, 100000)

def jp(arr):
    c = dict(zip(*np.unique(arr, return_counts=True)))
    res = arr[np.lexsort((arr, list(map(c.get, arr))))]
    return res

def perseus_sort(l):
    counter = Counter(l)
    return sorted(l, key=lambda x: (counter[x], x))

%timeit jp(arr)            # 39.2 ms
%timeit perseus_sort(arr)  # 118 ms
like image 43
jpp Avatar answered Feb 25 '26 08:02

jpp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!