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
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With