@Peter. Sí, ha ordenado la lista para fines de publicación. ¿La lista siempre estará ordenada?
S.Lott
2
No, la lista no se ordenará siempre. Esto no es tarea.
Bruce
Estoy tratando de trazar el gráfico de distribución de grados de una red.
Bruce
55
@ Peter: Actualice su pregunta con la información útil. No agregue comentarios a su pregunta: usted es el propietario de la pregunta, puede arreglarla para que sea completa y clara.
S.Lott
Respuestas:
147
Nota: Debe ordenar la lista antes de usar groupby.
Se puede utilizar groupbyde itertoolspaquete si la lista es una 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)]
agradable, usando groupby. Sin embargo, me pregunto acerca de su eficiencia frente al enfoque dict
Eli Bendersky,
32
Python groupby crea nuevos grupos cuando cambia el valor que ve. En este caso 1,1,1,2,1,1,1] devolvería [3,1,3]. Si esperaba [6,1], asegúrese de ordenar los datos antes de usar groupby.
Evan
44
@CristianCiupitu: sum(1 for _ in group).
Martijn Pieters
66
Esta no es una solución. La salida no dice lo que se contó.
buhtz
8
[(key, len(list(group))) for key, group in groupby(a)]o {key: len(list(group)) for key, group in groupby(a)}@buhtz
@unutbu: ¿Qué sucede si tengo tres listas, a, b, c para las cuales ayb siguen siendo las mismas, pero c cambia? ¿Cómo contar el valor de c para el cual ayc son iguales?
ThePredator
@Srivatsan: No entiendo la situación. Por favor, publique una nueva pregunta donde pueda elaborar.
unutbu
1
¿Hay alguna forma de extraer el diccionario {1: 4, 2: 4, 3: 2, 5: 2, 4: 1} del objeto contador?
Pavan
77
@Pavan: collections.Counteres una subclase de dict. Puede usarlo de la misma manera que lo haría con un dict normal. Sin embargo, si realmente quieres un dict, puedes convertirlo a un dict usando dict(counter).
unutbu
1
Trabaja en 3.6 también, por lo que suponen algo más grande que 2,7
kpierce8
108
Python 2.7+ presenta la comprensión del diccionario. Construir el diccionario a partir de la lista le dará el recuento y eliminará los duplicados.
>>> 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]
Esto funciona muy bien con listas de cadenas en lugar de números enteros como la pregunta original formulada.
Glen Selle
15
Es más rápido usar un conjunto:{x:a.count(x) for x in set(a)}
stenci
45
Esto es enormemente ineficiente . a.count()realiza un recorrido completo para cada elemento en a, haciendo de este un enfoque cuadrádico O (N ^ 2). collections.Counter()es mucho más eficiente porque cuenta en tiempo lineal (O (N)). En números, esto significa que este enfoque se ejecutarán 1 millón de pasos para una lista de longitud 1000, frente a sólo 1.000 pasos con Counter(), 10 ^ 12 pasos, donde sólo el 10 ^ 6 son necesarios por el contador por un millón de elementos de una lista, etc.
Martijn Pieters
3
@stenci: claro, pero el horror de usar a.count()completamente eclipsa la eficiencia de haber usado un set allí.
Martijn Pieters
2
@MartijnPieters una razón más para usarlo menos veces :)
stenci
48
Para contar el número de apariciones:
from collections import defaultdict
appearances = defaultdict(int)for curr in a:
appearances[curr]+=1
@phkahler: El mío sería solo un poquito mejor que esto. No vale la pena publicar una respuesta por separado cuando esto se puede mejorar con un pequeño cambio. El objetivo de SO es llegar a las mejores respuestas. Simplemente podría editar esto, pero prefiero permitirle al autor original la oportunidad de hacer sus propias mejoras.
S.Lott
1
@ S.Lott El código es mucho más limpio sin tener que importar defaultdict.
bstrauch24
¿Por qué no preinicializar b b = {k:0 for k in a}:?
DylanYoung
20
Aquí hay otra alternativa sucinta itertools.groupbyque también funciona para entradas no ordenadas:
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))}
Si bien este fragmento de código puede ser la solución, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y esas personas podrían no saber las razones de su sugerencia de código
Rahul Gupta
Sí lo hará 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.
el uso de listas countes ridículamente costoso y no se requiere en este escenario.
Idan K
@IdanK, ¿por qué contar es caro?
Kritika Rajain
@KritikaRajain Para cada elemento único en la lista, itera sobre toda la lista para generar un recuento (cuadrático en el número de elementos únicos en la lista). En su lugar, puede iterar sobre la lista una vez y contar el número de cada elemento único (lineal en el tamaño de la lista). Si su lista tiene solo un elemento único, el resultado será el mismo. Además, este enfoque requiere un conjunto intermedio adicional.
DylanYoung
7
Simplemente usaría scipy.stats.itemfreq de la siguiente manera:
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]
¿Puedes por favor dar más detalles sobre la primera respuesta
Bruce
3
Esta respuesta es más 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)
La colección de conjuntos no permite duplicados, pasar una lista al constructor set () dará un iterable de objetos totalmente únicos. La función count () devuelve una cuenta entera cuando se pasa un objeto que está en una lista. Con eso, los objetos únicos se cuentan y cada valor de conteo se almacena agregando a una salida de lista vacía
El constructor list () se utiliza para convertir el conjunto (a) en una lista y se hace referencia por la misma variable 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())no cambiará en el último bucle. No lo calcules en el ciclo, cómpralo antes del ciclo.
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)
No publique respuestas de solo código, pero aclare su código, especialmente cuando una pregunta ya tiene una respuesta 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]
Estoy usando Counter para generar una frecuencia. dict de palabras de archivo de texto en 1 línea 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])
Otra solución más con otro algoritmo sin usar colecciones:
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
Puede usar la función integrada proporcionada en 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])
El código anterior elimina automáticamente los duplicados en una lista y también imprime la frecuencia de cada elemento en la lista original y la lista sin duplicados.
>>> 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]
Es más limpio si también cuentas ceros:
>>> 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]
Una explicación:
comenzamos con una acclista vacía ;
si el siguiente elemento ede Les menor que el tamaño de acc, simplemente actualizamos este elemento: v+(i==e)significa v+1si el índice ide acces el elemento actual e, de lo contrario, el valor anterior v;
Si el siguiente elemento ede Les mayor o igual al tamaño de acc, tenemos que expandirnos accpara alojar el nuevo 1.
Los elementos no tienen que ser ordenados ( itertools.groupby). Obtendrás resultados extraños si tienes números negativos.
#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 el recuento de elementos únicos en una matriz ordenada usando el diccionario
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)
Una forma más es usar un diccionario y list.count, debajo de una forma ingenua de hacerlo.
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)
Respuestas:
Nota: Debe ordenar la lista antes de usar
groupby
.Se puede utilizar
groupby
deitertools
paquete si la lista es una lista ordenada.Salida:
fuente
groupby
. Sin embargo, me pregunto acerca de su eficiencia frente al enfoque dictsum(1 for _ in group)
.[(key, len(list(group))) for key, group in groupby(a)]
o{key: len(list(group)) for key, group in groupby(a)}
@buhtzEn Python 2.7 (o más reciente), puede usar
collections.Counter
:Si está utilizando Python 2.6 o anterior, puede descargarlo aquí .
fuente
collections.Counter
es una subclase dedict
. Puede usarlo de la misma manera que lo haría con un dict normal. Sin embargo, si realmente quieres un dict, puedes convertirlo a un dict usandodict(counter)
.Python 2.7+ presenta la comprensión del diccionario. Construir el diccionario a partir de la lista le dará el recuento y eliminará los duplicados.
fuente
{x:a.count(x) for x in set(a)}
a.count()
realiza un recorrido completo para cada elemento ena
, haciendo de este un enfoque cuadrádico O (N ^ 2).collections.Counter()
es mucho más eficiente porque cuenta en tiempo lineal (O (N)). En números, esto significa que este enfoque se ejecutarán 1 millón de pasos para una lista de longitud 1000, frente a sólo 1.000 pasos conCounter()
, 10 ^ 12 pasos, donde sólo el 10 ^ 6 son necesarios por el contador por un millón de elementos de una lista, etc.a.count()
completamente eclipsa la eficiencia de haber usado un set allí.Para contar el número de apariciones:
Para eliminar duplicados:
fuente
Counter
puede usar múltiples tipos numéricos, incluidosfloat
oDecimal
no soloint
.En Python 2.7+, puede usar colecciones. Contador para contar elementos
fuente
Contar la frecuencia de los elementos probablemente se haga mejor con un diccionario:
Para eliminar los duplicados, use un conjunto:
fuente
defaultdict
.b = {k:0 for k in a}
:?Aquí hay otra alternativa sucinta
itertools.groupby
que también funciona para entradas no ordenadas:resultados
fuente
Puedes hacerlo:
Salida:
La primera matriz son valores, y la segunda matriz es el número de elementos con estos valores.
Entonces, si desea obtener solo una matriz con los números, debe usar esto:
fuente
fuente
fuente
count
es ridículamente costoso y no se requiere en este escenario.Simplemente usaría scipy.stats.itemfreq de la siguiente manera:
Puede consultar la documentación aquí: http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.stats.itemfreq.html
fuente
Para su primera pregunta, repita la lista y use un diccionario para realizar un seguimiento de la existencia de un elemento.
Para su segunda pregunta, solo use el operador set.
fuente
Esta respuesta es más explícita.
fuente
...
fuente
Llego bastante tarde, pero esto también funcionará y ayudará a otros:
producirá esto ...
fuente
Salida
fuente
Solución simple usando un diccionario.
fuente
max(d.values())
no cambiará en el último bucle. No lo calcules en el ciclo, cómpralo antes del ciclo.fuente
fuente
Para eliminar duplicados y mantener el orden:
fuente
Estoy usando Counter para generar una frecuencia. dict de palabras de archivo de texto en 1 línea de código
fuente
Otro enfoque para hacer esto, aunque mediante el uso de una biblioteca más pesada pero poderosa, NLTK.
fuente
Otra solución más con otro algoritmo sin usar colecciones:
fuente
Puede usar la función integrada proporcionada en python
El código anterior elimina automáticamente los duplicados en una lista y también imprime la frecuencia de cada elemento en la lista original y la lista sin duplicados.
¡Dos pájaros para un disparo! XD
fuente
¡Este enfoque se puede probar si no desea utilizar ninguna biblioteca y mantenerla simple y breve!
o / p
fuente
Para el registro, una respuesta funcional:
Es más limpio si también cuentas ceros:
Una explicación:
acc
lista vacía ;e
deL
es menor que el tamaño deacc
, simplemente actualizamos este elemento:v+(i==e)
significav+1
si el índicei
deacc
es el elemento actuale
, de lo contrario, el valor anteriorv
;e
deL
es mayor o igual al tamaño deacc
, tenemos que expandirnosacc
para alojar el nuevo1
.Los elementos no tienen que ser ordenados (
itertools.groupby
). Obtendrás resultados extraños si tienes números negativos.fuente
Encontré otra forma de hacerlo, usando conjuntos.
fuente
fuente
Una forma más es usar un diccionario y list.count, debajo de una forma ingenua de hacerlo.
fuente
fuente