example - ¿Cómo uso itertools.groupby() de Python?
itertools python 3 (12)
Clasificación y groupby
from itertools import groupby
val = [{''name'': ''satyajit'', ''address'': ''btm'', ''pin'': 560076},
{''name'': ''Mukul'', ''address'': ''Silk board'', ''pin'': 560078},
{''name'': ''Preetam'', ''address'': ''btm'', ''pin'': 560076}]
for pin, list_data in groupby(sorted(val, key=lambda k: k[''pin'']),lambda x: x[''pin'']):
... print pin
... for rec in list_data:
... print rec
...
o/p:
560076
{''name'': ''satyajit'', ''pin'': 560076, ''address'': ''btm''}
{''name'': ''Preetam'', ''pin'': 560076, ''address'': ''btm''}
560078
{''name'': ''Mukul'', ''pin'': 560078, ''address'': ''Silk board''}
No he podido encontrar una explicación comprensible de cómo utilizar la función
itertools.groupby()
Python.
Lo que estoy tratando de hacer es esto:
-
Tome una lista: en este caso, los hijos de un elemento
lxml
objetivado - Divídelo en grupos según algunos criterios.
- Luego, itera más tarde sobre cada uno de estos grupos por separado.
He revisado la documentación y los ejemplos , pero he tenido problemas tratando de aplicarlos más allá de una simple lista de números.
Entonces, ¿cómo uso de
itertools.groupby()
?
¿Hay otra técnica que debería estar usando?
También se agradecerán los indicadores de una buena lectura de "requisitos previos".
¿Cómo uso itertools.groupby () de Python?
Puedes usar groupby para agrupar cosas para iterar sobre. Le da al grupo una función iterable, y una tecla opcional / llamable por medio de la cual puede verificar los elementos a medida que salen de la iterable, y devuelve un iterador que proporciona una doble tupla del resultado de la clave que se puede llamar y los elementos reales en otro iterable. De la ayuda:
groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).
Aquí hay un ejemplo de groupby usando una coroutine para agrupar por un conteo, usa una clave que se puede llamar (en este caso,
coroutine.send
) para simplemente escupir el conteo para muchas iteraciones y un sub-iterador de elementos agrupados:
import itertools
def grouper(iterable, n):
def coroutine(n):
yield # queue up coroutine
for i in itertools.count():
for j in range(n):
yield i
groups = coroutine(n)
next(groups) # queue up coroutine
for c, objs in itertools.groupby(iterable, groups.send):
yield c, list(objs)
# or instead of materializing a list of objs, just:
# return itertools.groupby(iterable, groups.send)
list(grouper(range(10), 3))
huellas dactilares
[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
¿Nos puedes mostrar tu código?
El ejemplo en los documentos de Python es bastante sencillo:
groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
groups.append(list(g)) # Store group iterator as a list
uniquekeys.append(k)
Entonces, en su caso, los datos son una lista de nodos, la función clave es donde va la lógica de su función de criterios y luego
groupby()
agrupa los datos.
Debe tener cuidado de
ordenar los datos
según el criterio antes de llamar a
groupby
o no funcionará.
groupby
método
groupby
realidad solo itera a través de una lista y cada vez que la clave cambia crea un nuevo grupo.
@CaptSolo, probé tu ejemplo, pero no funcionó.
from itertools import groupby
[(c,len(list(cs))) for c,cs in groupby(''Pedro Manoel'')]
Salida:
[(''P'', 1), (''e'', 1), (''d'', 1), (''r'', 1), (''o'', 1), ('' '', 1), (''M'', 1), (''a'', 1), (''n'', 1), (''o'', 1), (''e'', 1), (''l'', 1)]
Como puede ver, hay dos oes y dos e, pero se dividieron en grupos separados. Fue entonces cuando me di cuenta de que necesita ordenar la lista pasada a la función groupby. Entonces, el uso correcto sería:
name = list(''Pedro Manoel'')
name.sort()
[(c,len(list(cs))) for c,cs in groupby(name)]
Salida:
[('' '', 1), (''M'', 1), (''P'', 1), (''a'', 1), (''d'', 1), (''e'', 2), (''l'', 1), (''n'', 1), (''o'', 2), (''r'', 1)]
Solo recuerde, si la lista no está ordenada, ¡la función groupby no funcionará !
ADVERTENCIA:
La lista de sintaxis (groupby (...)) no funcionará de la forma que pretendía. Parece destruir los objetos iteradores internos, por lo que usar
for x in list(groupby(range(10))):
print(list(x[1]))
Producirá:
[]
[]
[]
[]
[]
[]
[]
[]
[]
[9]
En su lugar, de list (groupby (...)), intente [(k, list (g)) para k, g en groupby (...)], o si usa esa sintaxis a menudo,
def groupbylist(*args, **kwargs):
return [(k, list(g)) for k, g in groupby(*args, **kwargs)]
y obtenga acceso a la funcionalidad groupby evitando esos iteradores molestos (para datos pequeños) todos juntos.
Me gustaría dar otro ejemplo donde groupby sin orden no está funcionando. Adaptado del ejemplo por James Sulak.
from itertools import groupby
things = [("vehicle", "bear"), ("animal", "duck"), ("animal", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]
for key, group in groupby(things, lambda x: x[0]):
for thing in group:
print "A %s is a %s." % (thing[1], key)
print " "
la salida es
A bear is a vehicle.
A duck is a animal.
A cactus is a animal.
A speed boat is a vehicle.
A school bus is a vehicle.
Hay dos grupos con vehículo, mientras que uno podría esperar solo un grupo.
Otro ejemplo:
for key, igroup in itertools.groupby(xrange(12), lambda x: x // 5):
print key, list(igroup)
resultados en
0 [0, 1, 2, 3, 4]
1 [5, 6, 7, 8, 9]
2 [10, 11]
Tenga en cuenta que igroup es un iterador (un sub-iterador como lo llama la documentación).
Esto es útil para fragmentar un generador:
def chunker(items, chunk_size):
''''''Group items in chunks of chunk_size''''''
for _key, group in itertools.groupby(enumerate(items), lambda x: x[0] // chunk_size):
yield (g[1] for g in group)
with open(''file.txt'') as fobj:
for chunk in chunker(fobj):
process(chunk)
Otro ejemplo de groupby - cuando las claves no están ordenadas. En el siguiente ejemplo, los elementos en xx se agrupan por valores en yy. En este caso, primero se genera un conjunto de ceros, seguido de un conjunto de ceros, seguido de nuevo por un conjunto de ceros.
xx = range(10)
yy = [0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
for group in itertools.groupby(iter(xx), lambda x: yy[x]):
print group[0], list(group[1])
Produce:
0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]
Puedes escribir tu propia función groupby:
def groupby(data):
kv = {}
for k,v in data:
if k not in kv:
kv[k]=[v]
else:
kv[k].append(v)
return kv
Run on ipython:
In [10]: data = [(''a'', 1), (''b'',2),(''a'',2)]
In [11]: groupby(data)
Out[11]: {''a'': [1, 2], ''b'': [2]}
Un ejemplo útil que encontré puede ser útil:
from itertools import groupby
#user input
myinput = input()
#creating empty list to store output
myoutput = []
for k,g in groupby(myinput):
myoutput.append((len(list(g)),int(k)))
print(*myoutput)
Entrada de muestra: 14445221
Salida de muestra: (1,1) (3,4) (1,5) (2,2) (1,1)
Un truco nuevo con groupby es ejecutar la codificación de longitud en una línea:
[(c,len(list(cgen))) for c,cgen in groupby(some_string)]
le dará una lista de 2 tuplas donde el primer elemento es el carácter y el segundo es el número de repeticiones.
Edición: tenga en cuenta que esto es lo que separa
itertools.groupby
de la semántica
GROUP BY
: itertools no (y en general no puede) ordenar el iterador por adelantado, por lo que los grupos con la misma "clave" no se fusionan.
itertools.groupby
es una herramienta para agrupar elementos.
De los documentos , adivinamos más de lo que podría hacer:
# [k for k, g in groupby(''AAAABBBCCDAABBB'')] --> ABCDAB
# [list(g) for k, g in groupby(''AAAABBBCCD'')] --> AAAA BBB CC D
groupby
objetos
groupby
generan pares de grupos de claves donde el grupo es un generador.
Caracteristicas
- A. Agrupar elementos consecutivos juntos
- B. Agrupe todas las apariciones de un elemento, dado un iterable ordenado
- C. Especifique cómo agrupar elementos con una función clave
Comparaciones
# Define a printer for comparing outputs
>>> def print_groupby(iterable, key=None):
... for k, g in it.groupby(iterable, key):
... print("key: ''{}''--> group: {}".format(k, list(g)))
# Feature A: group consecutive occurrences
>>> print_groupby("BCAACACAADBBB")
key: ''B''--> group: [''B'']
key: ''C''--> group: [''C'']
key: ''A''--> group: [''A'', ''A'']
key: ''C''--> group: [''C'']
key: ''A''--> group: [''A'']
key: ''C''--> group: [''C'']
key: ''A''--> group: [''A'', ''A'']
key: ''D''--> group: [''D'']
key: ''B''--> group: [''B'', ''B'', ''B'']
# Feature B: group all occurrences
>>> print_groupby(sorted("BCAACACAADBBB"))
key: ''A''--> group: [''A'', ''A'', ''A'', ''A'', ''A'']
key: ''B''--> group: [''B'', ''B'', ''B'', ''B'']
key: ''C''--> group: [''C'', ''C'', ''C'']
key: ''D''--> group: [''D'']
# Feature C: group by a key function
>>> key = lambda x: x.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), key)
key: ''False''--> group: [''A'', ''A'', ''A'', ''B'', ''B'', ''C'', ''C'', ''D'']
key: ''True''--> group: [''a'', ''a'', ''b'', ''b'', ''c'']
Usos
- Anagrams ( ver cuaderno )
- Binning
- Grupo de números impares y pares
- Agrupar una lista por valores
- Eliminar elementos duplicados
- Encuentra índices de elementos repetidos en una matriz
- Dividir una matriz en trozos de tamaño n
- Encuentra elementos correspondientes entre dos listas
- Algoritmo de compresión ( ver cuaderno ) / Ejecutar codificación de longitud
- Agrupar letras por longitud, función clave ( ver cuaderno )
- Valores consecutivos sobre un umbral ( ver cuaderno )
- Encuentre rangos de números en una lista o elementos continuos (ver docs )
- Encuentra todas las secuencias más largas relacionadas
- Tomar secuencias consecutivas que cumplan una condición ( ver publicación relacionada )
Nota: Varios de los últimos ejemplos se derivan de PyCon
(talk)
(Spanish)
de Víctor Terrón, "Kung Fu at Dawn with Itertools".
Véase también el
código fuente
groupby
escrito en C.
Respuesta
# OP: Yes, you can use `groupby`, e.g.
[do_something(list(g)) for _, g in groupby(lxml_elements, key=criteria_func)]
NOTA IMPORTANTE: Primero debes ordenar tus datos .
La parte que no entendí es que en la construcción de ejemplo
groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
groups.append(list(g)) # Store group iterator as a list
uniquekeys.append(k)
k
es la clave de agrupación actual, y
g
es un iterador que puede usar para iterar sobre el grupo definido por esa clave de agrupación.
En otras palabras, el iterador
groupby
mismo devuelve iteradores.
Aquí hay un ejemplo de eso, usando nombres de variables más claros:
from itertools import groupby
things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]
for key, group in groupby(things, lambda x: x[0]):
for thing in group:
print "A %s is a %s." % (thing[1], key)
print " "
Esto le dará la salida:
Un oso es un animal.
Un pato es un animal.Un cactus es una planta.
Una lancha rápida es un vehículo.
Un autobús escolar es un vehículo.
En este ejemplo, las
things
son una lista de tuplas donde el primer elemento de cada tupla es el grupo al que pertenece el segundo elemento.
La función
groupby()
toma dos argumentos: (1) los datos para agrupar y (2) la función para
groupby()
.
Aquí,
lambda x: x[0]
le dice a
groupby()
que use el primer elemento de cada tupla como clave de agrupación.
En lo anterior
for
declaración,
groupby
devuelve tres pares (clave, iterador de grupo), una vez por cada clave única.
Puede usar el iterador devuelto para iterar sobre cada elemento individual en ese grupo.
Aquí hay un ejemplo ligeramente diferente con los mismos datos, utilizando una lista de comprensión:
for key, group in groupby(things, lambda x: x[0]):
listOfThings = " and ".join([thing[1] for thing in group])
print key + "s: " + listOfThings + "."
Esto le dará la salida:
Animales: oso y pato.
Plantas: Cactus.
Vehículos: lancha rápida y autobús escolar.