Ranking Elementos de várias listas por sua contagem em Python
Pergunta
Eu quero listas de classificação múltiplas de acordo com os seus elementos quantas vezes eles aparecem em cada lista. Exemplo:
list1 = 1,2,3,4
list2 = 4,5,6,7
list3 = 4,1,8,9
= resultado 4,1,2,3,4,5,6,7,8 (4 é contada três vezes, 1 duas vezes e uma vez que o resto)
Eu tentei o seguinte mas eu preciso de algo mais inteligente e algo que eu posso fazer com qualquer ammount de listas.
l = []
l.append([ 1, 2, 3, 4, 5])
l.append([ 1, 9, 3, 4, 5])
l.append([ 1, 10, 8, 4, 5])
l.append([ 1, 12, 13, 7, 5])
l.append([ 1, 14, 13, 13, 6])
x1 = set(l[0]) & set(l[1]) & set(l[2]) & set(l[3])
x2 = set(l[0]) & set(l[1]) & set(l[2]) & set(l[4])
x3 = set(l[0]) & set(l[1]) & set(l[3]) & set(l[4])
x4 = set(l[0]) & set(l[2]) & set(l[3]) & set(l[4])
x5 = set(l[1]) & set(l[2]) & set(l[3]) & set(l[4])
set1 = set(x1) | set(x2) | set(x3) | set(x4) | set(x5)
a1 = list(set(l[0]) & set(l[1]) & set(l[2]) & set(l[3]) & set(l[4]))
a2 = getDifference(list(set1),a1)
print a1
print a2
Agora, aqui está o problema ... eu posso fazê-lo novamente e novamente com o A3, A4 e A5, mas a sua demasiado complexo, em seguida, eu preciso de uma função para isso ... Mas eu não sei como ... o meu matemática ficou preso;)
resolvido: muito obrigado para a discussão. Como i newbee como este sistema de alguma forma: fast + informativo. Você me ajudou todos para fora! Ty
Solução
import collections
data = [
[1, 2, 3, 4, 5],
[1, 9, 3, 4, 5],
[1, 10, 8, 4, 5],
[1, 12, 13, 7, 5],
[1, 14, 13, 13, 6],
]
def sorted_by_count(lists):
counts = collections.defaultdict(int)
for L in lists:
for n in L:
counts[n] += 1
return [num for num, count in
sorted(counts.items(),
key=lambda k_v: (k_v[1], k_v[0]),
reverse=True)]
print sorted_by_count(data)
Agora vamos generalizar-lo (para tomar qualquer, exigência Hashable soltar iterable), permite que os parâmetros-chave e reversa (para combinar classificadas), e renomeie a freq_sorted :
def freq_sorted(iterable, key=None, reverse=False, include_freq=False):
"""Return a list of items from iterable sorted by frequency.
If include_freq, (item, freq) is returned instead of item.
key(item) must be hashable, but items need not be.
*Higher* frequencies are returned first. Within the same frequency group,
items are ordered according to key(item).
"""
if key is None:
key = lambda x: x
key_counts = collections.defaultdict(int)
items = {}
for n in iterable:
k = key(n)
key_counts[k] += 1
items.setdefault(k, n)
if include_freq:
def get_item(k, c):
return items[k], c
else:
def get_item(k, c):
return items[k]
return [get_item(k, c) for k, c in
sorted(key_counts.items(),
key=lambda kc: (-kc[1], kc[0]),
reverse=reverse)]
Exemplo:
>>> import itertools
>>> print freq_sorted(itertools.chain.from_iterable(data))
[1, 5, 4, 13, 3, 2, 6, 7, 8, 9, 10, 12, 14]
>>> print freq_sorted(itertools.chain.from_iterable(data), include_freq=True)
# (slightly reformatted)
[(1, 5),
(5, 4),
(4, 3), (13, 3),
(3, 2),
(2, 1), (6, 1), (7, 1), (8, 1), (9, 1), (10, 1), (12, 1), (14, 1)]
Outras dicas
combinando um par de ideias já postou:
from itertools import chain
from collections import defaultdict
def frequency(*lists):
counter = defaultdict(int)
for x in chain(*lists):
counter[x] += 1
return [key for (key, value) in
sorted(counter.items(), key=lambda kv: (kv[1], kv[0]), reverse=True)]
Notas:
- Em Python 2.7, você pode usar
Counter
vez dedefaultdict(int)
. - Esta versão leva qualquer número de listas como seu argumento; os meios principais asterisco todos eles vão ser embalado em uma tupla. Se você quer passar em uma única lista contendo todas as suas listas, omitir que liderar asterisco.
- Isto quebra se suas listas contêm um tipo unhashable.
def items_ordered_by_frequency(*lists):
# get a flat list with all the values
biglist = []
for x in lists:
biglist += x
# sort it in reverse order by frequency
return sorted(set(biglist),
key=lambda x: biglist.count(x),
reverse=True)
Tente esta:
def rank(*lists):
d = dict()
for lst in lists:
for e in lst:
if e in d: d[e] += 1
else: d[e] = 1
return [j[1] for j in sorted([(d[i],i) for i in d], reverse=True)]
Exemplo de uso:
a = [1,2,3,4]
b = [4,5,6,7]
c = [4,1,8,9]
print rank(a,b,c)
Você pode usar qualquer número de listas como entrada
Você pode contar o número de aparições de cada elemento (um histograma), em seguida, classificar por ela:
def histogram(enumerable):
result = {}
for x in enumerable:
result.setdefault(x, 0)
result[x] += 1
return result
lists = [ [1,2,3,4], [4,5,6,7], ... ]
from itertools import chain
h = histogram(chain(*lists))
ranked = sorted(set(chain(*lists)), key = lambda x : h[x], reverse = True)
Tente este código:
def elementFreq(myList):
#myList is the list of lists
from collections import Counter
tmp = []
for i in myList: tmp += i
return(Counter(tmp))
Nota: Suas listas devem ser do tipo Hashable