@Peter. Sim, você classificou a lista para fins de postagem. A lista será sempre classificada?
precisa saber é o seguinte
2
Não, a lista nem sempre será classificada. Isso não é lição de casa.
Bruce
Estou tentando traçar o gráfico da distribuição de graus de uma rede.
Bruce Bruce
5
@ Peter: Por favor, atualize sua pergunta com as informações úteis. Não adicione comentários à sua pergunta - você é o proprietário da pergunta, pode corrigi-la para ser completa e clara.
precisa saber é o seguinte
Respostas:
147
Nota: Você deve classificar a lista antes de usar groupby.
Você pode usar groupbydo itertoolspacote se a lista for uma lista ordenada.
a =[1,1,1,1,2,2,2,2,3,3,4,5,5]from itertools import groupby
[len(list(group))for key, group in groupby(a)]
bom, usando groupby. Eu me pergunto sobre a sua eficiência vs. a abordagem dict, embora
Eli Bendersky
32
O python groupby cria novos grupos quando o valor que vê é alterado. Nesse caso, 1,1,1,2,1,1,1] retornaria [3,1,3]. Se você esperava [6,1], apenas certifique-se de classificar os dados antes de usar o groupby.
Evan
4
@CristianCiupitu: sum(1 for _ in group).
Martijn Pieters
6
Esta não é uma solução. A saída não diz o que foi contado.
buhtz
8
[(key, len(list(group))) for key, group in groupby(a)]ou {key: len(list(group)) for key, group in groupby(a)}@buhtz
@unutbu: E se eu tiver três listas, a, b, c para as quais aeb permanecem os mesmos, mas c muda? Como contar o valor de c para o qual a e c são iguais?
ThePredator
@Srivatsan: Eu não entendo a situação. Por favor, poste uma nova pergunta onde você pode elaborar.
Unutbu
1
Existe uma maneira de extrair o dicionário {1: 4, 2: 4, 3: 2, 5: 2, 4: 1} do objeto contador?
Pavan
7
@Pavan: collections.Counteré uma subclasse de dict. Você pode usá-lo da mesma maneira que faria com um ditado normal. Se você realmente quer um ditado, no entanto, você pode convertê-lo em um ditado usando dict(counter).
unutbu 22/03/2015
1
Obras em 3.6 também, por isso, assumir nada maior do que 2,7
kpierce8
108
O Python 2.7+ apresenta a Compreensão do Dicionário. Criar o dicionário a partir da lista fará com que você obtenha a contagem e se livre de duplicatas.
>>> a =[1,1,1,1,2,2,2,2,3,3,4,5,5]>>> d ={x:a.count(x)for x in a}>>> d
{1:4,2:4,3:2,4:1,5:2}>>> a, b = d.keys(), d.values()>>> a
[1,2,3,4,5]>>> b
[4,4,2,1,2]
Isso funciona muito bem com listas de strings em oposição a números inteiros, como a pergunta original.
Glen Selle
15
É mais rápido usando um conjunto:{x:a.count(x) for x in set(a)}
stenci 17/02
45
Isso é extremamente ineficiente . a.count()faz uma travessia completa para cada elemento a, tornando essa uma abordagem quadrática O (N ^ 2). collections.Counter()é muito mais eficiente porque conta em tempo linear (O (N)). Em números, isso significa que essa abordagem executará 1 milhão de etapas para uma lista de 1000, contra apenas 1000 etapas com Counter(), 10 ^ 12 etapas em que apenas 10 ^ 6 são necessárias pelo contador para um milhão de itens em uma lista etc.
Martijn Pieters
3
@stenci: claro, mas o horror de usar a.count()completamente diminui a eficiência de ter usado um conjunto lá.
Martijn Pieters
2
@MartijnPieters mais uma razão para usá-lo menos vezes :)
stenci
48
Para contar o número de aparências:
from collections import defaultdict
appearances = defaultdict(int)for curr in a:
appearances[curr]+=1
@phkahler: O meu seria apenas um pouquinho melhor do que isso. Não vale a pena postar uma resposta separada quando isso puder ser melhorado com uma pequena alteração. O objetivo do SO é obter as melhores respostas. Eu poderia simplesmente editar isso, mas prefiro permitir ao autor original a chance de fazer suas próprias melhorias.
precisa saber é o seguinte
1
@ S.Lott O código é muito mais limpo sem ter que importar defaultdict.
bstrauch24
Por que não pré-inicializar b b = {k:0 for k in a}:?
DylanYoung
20
Aqui está outra alternativa succint itertools.groupbyque também funciona para entrada não ordenada:
from itertools import groupby
items =[5,1,1,2,2,1,1,2,2,3,4,3,5]
results ={value: len(list(freq))for value, freq in groupby(sorted(items))}
Embora esse snippet de código possa ser a solução, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se que você está respondendo a pergunta para os leitores no futuro, e essas pessoas podem não saber as razões para a sua sugestão de código
Rahul Gupta
Sim fará isso Rahul Gupta
Anirban Lahiri
7
seta = set(a)
b =[a.count(el)for el in seta]
a = list(seta)#Only if you really want it.
o uso de listas counté ridiculamente caro e desnecessário nesse cenário.
Idan K
@IdanK por que contar é caro?
Kritika Rajain
@KritikaRajain Para cada elemento exclusivo da lista, você itera sobre a lista inteira para gerar uma contagem (quadrático no número de elementos exclusivos da lista). Em vez disso, você pode percorrer a lista uma vez e contar o número de cada elemento exclusivo (linear no tamanho da lista). Se sua lista tiver apenas um elemento exclusivo, o resultado será o mesmo. Além disso, essa abordagem requer um conjunto intermediário adicional.
DylanYoung
7
Eu simplesmente usaria scipy.stats.itemfreq da seguinte maneira:
from scipy.stats import itemfreq
a =[1,1,1,1,2,2,2,2,3,3,4,5,5]
freq = itemfreq(a)
a = freq[:,0]
b = freq[:,1]
Você pode por favor elaborar sobre a primeira resposta
Bruce
3
Esta resposta é mais explícita
a =[1,1,1,1,2,2,2,2,3,3,3,4,4]
d ={}for item in a:if item in d:
d[item]= d.get(item)+1else:
d[item]=1for k,v in d.items():print(str(k)+':'+str(v))# output#1:4#2:4#3:3#4:2#remove dups
d = set(a)print(d)#{1, 2, 3, 4}
a =[1,1,1,1,2,2,2,2,3,3,4,5,5]# 1. Get counts and store in another list
output =[]for i in set(a):
output.append(a.count(i))print(output)# 2. Remove duplicates using set constructor
a = list(set(a))print(a)
A coleção de conjuntos não permite duplicatas, passar uma lista para o construtor set () fornecerá uma iterabilidade de objetos totalmente exclusivos. A função count () retorna uma contagem inteira quando um objeto que está em uma lista é passado. Com isso, os objetos exclusivos são contados e cada valor de contagem é armazenado anexando a uma saída de lista vazia
O construtor list () é usado para converter o conjunto (a) em lista e referido pela mesma variável a
def frequency(l):
d ={}for i in l:if i in d.keys():
d[i]+=1else:
d[i]=1for k, v in d.iteritems():if v ==max (d.values()):return k,d.keys()print(frequency([10,10,10,10,20,20,20,20,40,40,50,50,30]))
max(d.values())não será alterado no último loop. Não o calcule no loop, antes do loop.
DylanYoung
1
#!usr/bin/pythondef frq(words):
freq ={}for w in words:if w in freq:
freq[w]= freq.get(w)+1else:
freq[w]=1return freq
fp = open("poem","r")
list = fp.read()
fp.close()
input = list.split()print input
d = frq(input)print"frequency of input\n: "print d
fp1 = open("output.txt","w+")for k,v in d.items():
fp1.write(str(k)+':'+str(v)+"\n")
fp1.close()
num=[3,2,3,5,5,3,7,6,4,6,7,2]print('\nelements are:\t',num)
count_dict={}for elements in num:
count_dict[elements]=num.count(elements)print('\nfrequency:\t',count_dict)
Não poste respostas somente de código, mas esclareça seu código, especialmente quando uma pergunta já tiver uma resposta válida.
Erik A
1
from collections importOrderedDict
a =[1,1,1,1,2,2,2,2,3,3,4,5,5]def get_count(lists):
dictionary =OrderedDict()for val in lists:
dictionary.setdefault(val,[]).append(1)return[sum(val)for val in dictionary.values()]print(get_count(a))>>>[4,4,2,1,2]
Estou usando o contador para gerar um freq. ditar palavras de arquivo de texto em 1 linha de código
def _fileIndex(fh):''' create a dict using Counter of a
flat list of words (re.findall(re.compile(r"[a-zA-Z]+"), lines)) in (lines in file->for lines in fh)
'''returnCounter([wrd.lower()for wrdList in[words for words in[re.findall(re.compile(r'[a-zA-Z]+'), lines)for lines in fh]]for wrd in wrdList])
Mais uma solução com outro algoritmo sem usar coleções:
def countFreq(A):
n=len(A)
count=[0]*n # Create a new list initialized with '0'for i in range(n):
count[A[i]]+=1# increase occurrence for value A[i]return[x for x in count if x]# return non-zero count
Você pode usar a função interna fornecida em python
l.count(l[i])
d=[]for i in range(len(l)):if l[i]notin d:
d.append(l[i])print(l.count(l[i])
O código acima remove automaticamente duplicatas em uma lista e também imprime a frequência de cada elemento na lista original e na lista sem duplicatas.
>>> L =[1,1,1,1,2,2,2,2,3,3,4,5,5]>>>import functools
>>>>>> functools.reduce(lambda acc, e:[v+(i==e)for i, v in enumerate(acc,1)]if e<=len(acc)else acc+[0for _ in range(e-len(acc)-1)]+[1], L,[])[4,4,2,1,2]
É mais limpo se você contar zeros também:
>>> functools.reduce(lambda acc, e:[v+(i==e)for i, v in enumerate(acc)]if e<len(acc)else acc+[0for _ in range(e-len(acc))]+[1], L,[])[0,4,4,2,1,2]
Uma explicação:
começamos com um vazio acc lista ;
se o próximo elemento ede Lfor menor que o tamanho de acc, basta atualizar esse elemento: v+(i==e)significa v+1se o índice ide accé o elemento atual e, caso contrário, o valor anterior v;
se o próximo elemento ede Lfor maior ou igual ao tamanho de acc, teremos que expandir accpara hospedar o novo 1.
Os elementos não precisam ser classificados ( itertools.groupby). Você obterá resultados estranhos se tiver números negativos.
Encontrou outra maneira de fazer isso, usando conjuntos.
#ar is the list of elements#convert ar to set to get unique elements
sock_set = set(ar)#create dictionary of frequency of socks
sock_dict ={}for sock in sock_set:
sock_dict[sock]= ar.count(sock)
Para encontrar a contagem de elementos exclusivos em uma matriz classificada usando o dicionário
defCountFrequency(my_list):# Creating an empty dictionary
freq ={}for item in my_list:if(item in freq):
freq[item]+=1else:
freq[item]=1for key, value in freq.items():print("% d : % d"%(key, value))# Driver function if __name__ =="__main__":
my_list =[1,1,1,5,5,3,1,3,3,1,4,4,4,2,2,2,2]CountFrequency(my_list)
Mais uma maneira é usar um dicionário e o list.count, abaixo de uma maneira ingênua de fazê-lo.
dicio = dict()
a =[1,1,1,1,2,2,2,2,3,3,4,5,5]
b = list()
c = list()for i in a:if i in dicio:continueelse:
dicio[i]= a.count(i)
b.append(a.count(i))
c.append(i)print(b)print(c)
Respostas:
Nota: Você deve classificar a lista antes de usar
groupby
.Você pode usar
groupby
doitertools
pacote se a lista for uma lista ordenada.Resultado:
fonte
groupby
. Eu me pergunto sobre a sua eficiência vs. a abordagem dict, emborasum(1 for _ in group)
.[(key, len(list(group))) for key, group in groupby(a)]
ou{key: len(list(group)) for key, group in groupby(a)}
@buhtzNo Python 2.7 (ou mais recente), você pode usar
collections.Counter
:Se você estiver usando o Python 2.6 ou mais antigo, faça o download aqui .
fonte
collections.Counter
é uma subclasse dedict
. Você pode usá-lo da mesma maneira que faria com um ditado normal. Se você realmente quer um ditado, no entanto, você pode convertê-lo em um ditado usandodict(counter)
.O Python 2.7+ apresenta a Compreensão do Dicionário. Criar o dicionário a partir da lista fará com que você obtenha a contagem e se livre de duplicatas.
fonte
{x:a.count(x) for x in set(a)}
a.count()
faz uma travessia completa para cada elementoa
, tornando essa uma abordagem quadrática O (N ^ 2).collections.Counter()
é muito mais eficiente porque conta em tempo linear (O (N)). Em números, isso significa que essa abordagem executará 1 milhão de etapas para uma lista de 1000, contra apenas 1000 etapas comCounter()
, 10 ^ 12 etapas em que apenas 10 ^ 6 são necessárias pelo contador para um milhão de itens em uma lista etc.a.count()
completamente diminui a eficiência de ter usado um conjunto lá.Para contar o número de aparências:
Para remover duplicatas:
fonte
Counter
pode usar vários tipos numéricos, incluindofloat
ouDecimal
não apenasint
.No Python 2.7+, você pode usar coleções. Contador para contar itens
fonte
Contar a frequência dos elementos é provavelmente o melhor feito com um dicionário:
Para remover as duplicatas, use um conjunto:
fonte
defaultdict
.b = {k:0 for k in a}
:?Aqui está outra alternativa succint
itertools.groupby
que também funciona para entrada não ordenada:resultados
fonte
Você consegue fazer isso:
Resultado:
A primeira matriz é valores e a segunda matriz é o número de elementos com esses valores.
Portanto, se você deseja obter apenas uma matriz com os números, use este:
fonte
fonte
fonte
count
é ridiculamente caro e desnecessário nesse cenário.Eu simplesmente usaria scipy.stats.itemfreq da seguinte maneira:
você pode verificar a documentação aqui: http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.stats.itemfreq.html
fonte
Para sua primeira pergunta, itere a lista e use um dicionário para acompanhar a existência de um elemento.
Para sua segunda pergunta, basta usar o operador set.
fonte
Esta resposta é mais explícita
fonte
...
fonte
Estou muito atrasado, mas isso também funcionará e ajudará outros:
irá produzir isso ..
fonte
Resultado
fonte
Solução simples usando um dicionário.
fonte
max(d.values())
não será alterado no último loop. Não o calcule no loop, antes do loop.fonte
fonte
Para remover duplicatas e manter ordem:
fonte
Estou usando o contador para gerar um freq. ditar palavras de arquivo de texto em 1 linha de código
fonte
Outra abordagem para fazer isso, embora usando uma biblioteca mais pesada, porém poderosa - o NLTK.
fonte
Mais uma solução com outro algoritmo sem usar coleções:
fonte
Você pode usar a função interna fornecida em python
O código acima remove automaticamente duplicatas em uma lista e também imprime a frequência de cada elemento na lista original e na lista sem duplicatas.
Dois pássaros por um tiro! XD
fonte
Essa abordagem pode ser tentada se você não quiser usar nenhuma biblioteca e mantê-la simples e curta!
o / p
fonte
Para o registro, uma resposta funcional:
É mais limpo se você contar zeros também:
Uma explicação:
acc
lista ;e
deL
for menor que o tamanho deacc
, basta atualizar esse elemento:v+(i==e)
significav+1
se o índicei
deacc
é o elemento atuale
, caso contrário, o valor anteriorv
;e
deL
for maior ou igual ao tamanho deacc
, teremos que expandiracc
para hospedar o novo1
.Os elementos não precisam ser classificados (
itertools.groupby
). Você obterá resultados estranhos se tiver números negativos.fonte
Encontrou outra maneira de fazer isso, usando conjuntos.
fonte
fonte
Mais uma maneira é usar um dicionário e o list.count, abaixo de uma maneira ingênua de fazê-lo.
fonte
fonte