Cuente la frecuencia de una lista recurrente – dentro de una lista de listas

Tengo una lista de listas en python y necesito encontrar cuántas veces ha ocurrido cada sub-lista. Aquí hay una muestra,

from collections import Counter list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333], [ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333]] c = Counter(x for x in iter(list1)) print c 

El código anterior funcionará si los elementos de la lista fueran hashable (por ejemplo, int), pero en este caso son listas y aparece un error.

 TypeError: unhashable type: 'list' 

¿Cómo puedo contar estas listas para obtener algo como

 [ 1., 2.66666667, 1.33333333], 3 [ 1., 4., 2.5], 2 [ 1., 2., 2.], 1 

Solo convierte las listas a tuple :

 >>> c = Counter(tuple(x) for x in iter(list1)) >>> c Counter({(1.0, 2.66666667, 1.33333333): 3, (1.0, 4.0, 2.5): 2, (1.0, 2.0, 2.0): 1}) 

Recuerda hacer lo mismo para buscar:

 >>> c[tuple(list1[0])] 2 

El contador devuelve un objeto similar al diccionario que sus claves deben ser hashable. Y como las listas no son hashables, puedes convertirlas en tuple usando la función de map :

 >>> Counter(map(tuple, list1)) Counter({(1.0, 2.66666667, 1.33333333): 3, (1.0, 4.0, 2.5): 2, (1.0, 2.0, 2.0): 1}) 

Tenga en cuenta que el uso del map tendrá un rendimiento ligeramente mejor que el de una expresión generadora, ya que al pasar una expresión generadora a Counter() python obtendrá los valores de la función del generador por sí mismo, ya que el uso del map función incorporado tiene más rendimiento en términos de tiempo de ejecución 1 .

 # Use generator expression ~ $ python -m timeit --setup "list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333],[ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5],[ 1., 2.66666667, 1.33333333]] ;from collections import Counter" "Counter(tuple(x) for x in iter(list1))" 100000 loops, best of 3: 9.86 usec per loop # Use map ~ $ python -m timeit --setup "list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333],[ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5],[ 1., 2.66666667, 1.33333333]] ;from collections import Counter" "Counter(map(tuple, list1))" 100000 loops, best of 3: 7.92 usec per loop 

De PEP 0289 – Expresiones del generador :

La semántica de una expresión generadora es equivalente a crear una función generadora anónima y llamarla. Por ejemplo:

 g = (x**2 for x in range(10)) print g.next() 

es equivalente a:

 def __gen(exp): for x in exp: yield x**2 g = __gen(iter(range(10))) print g.next() 

Tenga en cuenta que dado que las expresiones del generador son mejores en términos de uso de la memoria, si está tratando con datos grandes, es mejor que use la expresión del generador en lugar de la función de mapa .

Prueba esto

 list1 = [[ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333], [ 1., 2., 2.], [ 1., 2.66666667, 1.33333333], [ 1., 4., 2.5], [ 1., 2.66666667, 1.33333333]] counter = {} for el in list1: el = str(el) #This sorts your hashable part or use tuple(el) if el in counter: counter[el]+=1 else: counter[el]=1 print(counter) 

Debe salir

 {'[1.0, 2.0, 2.0]': 1, '[1.0, 2.66666667, 1.33333333]': 3, '[1.0, 4.0, 2.5]': 2}