22

Is there any way in Python, wherein I can sort a list by its frequency?

For example,

[1,2,3,4,3,3,3,6,7,1,1,9,3,2]

the above list would be sorted in the order of the frequency of its values to create the following list, where the item with the greatest frequency is placed at the front:

[3,3,3,3,3,1,1,1,2,2,4,6,7,9]
Georgy
  • 6,348
  • 7
  • 46
  • 58
user2592835
  • 1,201
  • 2
  • 14
  • 24

7 Answers7

35

I think this would be a good job for a collections.Counter:

counts = collections.Counter(lst)
new_list = sorted(lst, key=lambda x: -counts[x])

Alternatively, you could write the second line without a lambda:

counts = collections.Counter(lst)
new_list = sorted(lst, key=counts.get, reverse=True)

If you have multiple elements with the same frequency and you care that those remain grouped, we can do that by changing our sort key to include not only the counts, but also the value:

counts = collections.Counter(lst)
new_list = sorted(lst, key=lambda x: (counts[x], x), reverse=True)
mgilson
  • 264,617
  • 51
  • 541
  • 636
5
l = [1,2,3,4,3,3,3,6,7,1,1,9,3,2]
print sorted(l,key=l.count,reverse=True)

[3, 3, 3, 3, 3, 1, 1, 1, 2, 2, 4, 6, 7, 9]
Padraic Cunningham
  • 160,756
  • 20
  • 201
  • 286
  • 10
    This has the disadvantage of every call to `key` being O(n), where with `collections.Counter` it's O(1), with a single O(n) call to build the `Counter` (I didn't downvote, just wanted to point out the efficiency difference). – dano Sep 12 '14 at 19:30
  • 1
    It is a oneliner but I guess its algorithmic complexity is O(n^2). Using `collections.Counter` avoids counting occurences of each item for each item in the list. – rhlobo Sep 12 '14 at 19:38
2

You can use a Counter to get the count of each item, use its most_common method to get it in sorted order, then use a list comprehension to expand again

>>> lst = [1,2,3,4,3,3,3,6,7,1,1,9,3,2]
>>> 
>>> from collections import Counter
>>> [n for n,count in Counter(lst).most_common() for i in range(count)]
[3, 3, 3, 3, 3, 1, 1, 1, 2, 2, 4, 6, 7, 9]
Sunitha
  • 11,046
  • 2
  • 14
  • 21
2

In case you want to use a double comparator.

For example: Sort the list by frequency in descending order and in case of a clash the smaller one comes first.

import collections 

def frequency_sort(a):
    f = collections.Counter(a)
    a.sort(key = lambda x:(-f[x], x))
    return a
Ankit Sharma
  • 1,035
  • 11
  • 15
1

Was practising this one for fun. This solution use less time complexity.

from collections import defaultdict

lis = [1,2,3,4,3,3,3,6,7,1,1,9,3,2]

dic = defaultdict(int)
for num in lis:
    dic[num] += 1

s_list = sorted(dic, key=dic.__getitem__, reverse=True)

new_list = []
for num in s_list:
    for rep in range(dic[num]):
        new_list.append(num)

print(new_list)
gautamaggarwal
  • 291
  • 2
  • 10
-3
from collections import Counter
a = [2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8]
count = Counter(a)
a = []
while len(count) > 0:
    c = count.most_common(1)
    for i in range(c[0][1]):
        a.append(c[0][0])
    del count[c[0][0]]
print(a)
ndmeiri
  • 4,728
  • 12
  • 32
  • 41
  • 1
    It is always better to include a few comments about why your answer works / is the best solution - to help OP & future visitors. – Nerdi.org Jul 26 '18 at 19:38
-4

You can use below methods. It is written in simple python.

def frequencyIdentification(numArray):
frequency = dict({});
for i in numArray:
    if i in frequency.keys():
            frequency[i]=frequency[i]+1;
    else:
            frequency[i]=1;         
return frequency;

def sortArrayBasedOnFrequency(numArray):
    sortedNumArray = []
    frequency = frequencyIdentification(numArray);
    frequencyOrder = sorted(frequency, key=frequency.get);
    loop = 0;
    while len(frequencyOrder) > 0:
        num = frequencyOrder.pop()
        count = frequency[num];
        loop = loop+1;
        while count>0:
            loop = loop+1;
            sortedNumArray.append(num);
            count=count-1;
    print("loop count");
    print(loop);
    return sortedNumArray;  

a=[1, 2, 3, 4, 3, 3, 3, 6, 7, 1, 1, 9, 3, 2]
print(a);
print("sorted array based on frequency of the number"); 
print(sortArrayBasedOnFrequency(a));
AVVD
  • 58
  • 1
  • 10