Comment utiliser les itertools de Python?groupby()?
Je n'ai pas été en mesure de trouver une explication compréhensible de la façon d'utiliser réellement la fonction itertools.groupby()
de Python. Ce que j'essaie de faire c'est ceci:
- Prendre une liste - dans ce cas, les enfants d'un objectivé
lxml
élément - divisez-le en groupes en fonction de certains critères
- puis itérer séparément sur chacun de ces groupes.
j'ai revu la documentation , et exemples , mais j'ai eu du mal à essayer de les appliquer au-delà d'une simple liste de nombres.
alors, comment utiliser itertools.groupby()
? Est-il une autre technique que je devrais utiliser? Des conseils sur la bonne lecture des" conditions préalables " seraient également appréciés.
11 réponses
comme a dit Sebastjan, vous devez d'abord trier vos données. Ce qui est important.
la partie que je n'ai pas obtenu est que dans l'exemple de construction
groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
groups.append(list(g)) # Store group iterator as a list
uniquekeys.append(k)
k
est la clé de regroupement courante, et g
est un itérateur que vous pouvez utiliser pour itérer sur le groupe défini par cette clé de regroupement. En d'autres termes, l'itérateur groupby
renvoie lui-même les itérateurs.
Voici un exemple de cela, en utilisant des noms de variables plus clairs:
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 " "
Cela vous donnera la sortie:
un ours est un animal.
Un canard est un animal.un cactus est une plante.
un bateau rapide est un véhicule.
Un autobus est un véhicule.
Dans cet exemple, things
est un liste de tuples où le premier élément de chaque tuple est le groupe le deuxième élément appartient.
la fonction groupby()
prend deux arguments: (1) les données à grouper et (2) la fonction à grouper avec.
ici, lambda x: x[0]
dit groupby()
d'utiliser le premier élément de chaque tuple comme clé de regroupement.
dans l'énoncé ci-dessus for
, groupby
renvoie trois paires (clé, itérateur de groupe) - une pour chaque paire clé unique. Vous pouvez utiliser l'itérateur retourné pour itérer sur chaque élément individuel dans ce groupe.
voici un exemple légèrement différent avec les mêmes données, en utilisant une liste de compréhension:
for key, group in groupby(things, lambda x: x[0]):
listOfThings = " and ".join([thing[1] for thing in group])
print key + "s: " + listOfThings + "."
Cela vous donnera la sortie:
animaux: ours et canard.
plantes: cactus.
véhicules: bateau à moteur et autobus scolaire.
pouvez-vous nous montrer votre code?
l'exemple sur Python docs est assez simple:
groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
groups.append(list(g)) # Store group iterator as a list
uniquekeys.append(k)
donc dans votre cas, data est une liste de noeuds, keyfunc est où la logique de votre fonction de critères va et puis groupby()
regroupe les données.
vous devez faire attention à trier les données par les critères avant d'appeler groupby
sinon ça ne marchera pas. groupby
méthode en fait juste itérates à travers une liste et chaque fois que la clé change elle crée un nouveau groupe.
un truc de Neato avec groupby est de lancer le codage de longueur en une seule ligne:
[(c,len(list(cgen))) for c,cgen in groupby(some_string)]
vous donnera une liste de 2-tuples dont le premier élément est le char et le 2ème est le nombre de répétitions.
Edit: notez que c'est ce qui sépare itertools.groupby
du SQL GROUP BY
sémantique: itertools ne trie pas (et en général ne peut pas) trier l'itérateur à l'avance, donc les groupes avec la même "clé" ne sont pas fusionnés.
autre exemple:
for key, igroup in itertools.groupby(xrange(12), lambda x: x // 5):
print key, list(igroup)
résultats dans
0 [0, 1, 2, 3, 4]
1 [5, 6, 7, 8, 9]
2 [10, 11]
notez que groupe est un itérateur (un sous-itérateur comme la documentation l'appelle).
c'est utile pour réparer un générateur:
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)
un autre exemple de groupby-lorsque les clés ne sont pas triées. Dans l'exemple suivant, les éléments de xx sont groupés par les valeurs de yy. Dans ce cas, un jeu de zéros est sorti en premier., suivie par une série d', suivi de nouveau par un ensemble de zéros.
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])
produit:
0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]
avertissement:
la liste de syntaxe (groupby(...)) ne fonctionneront pas de la manière que vous voulez. Il semble détruire les objets iterator internes, donc en utilisant
for x in list(groupby(range(10))):
print(list(x[1]))
produira:
[]
[]
[]
[]
[]
[]
[]
[]
[]
[9]
au lieu de listby (...)), essayez de [(k, liste(g)) pour k,g dans groupby(...)], ou si vous utilisez souvent cette syntaxe,
def groupbylist(*args, **kwargs):
return [(k, list(g)) for k, g in groupby(*args, **kwargs)]
et accéder à la fonctionnalité groupby tout en évitant ces pestes (pour les petits de données) itérateurs tous ensemble.
itertools.groupby
est un outil pour grouper des articles.
à Partir de les docs , nous glaner le plus de ce qu'il pourrait faire:
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
groupby
objets rendement clé-paires de groupes où le groupe est un générateur.
Caractéristiques
- A. Groupe d'éléments consécutifs ensemble
- B. grouper toutes les occurrences d'un élément, donné un tri itérable
- C. spécifier comment grouper des éléments avec une fonction clé
comparaisons
# 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']
Utilise
- anagrammes ( voir carnet )
- Binning
- Groupe impair et même des numéros de
- Groupe a liste avec valeurs
- supprimer les éléments en double
- trouver des indices d'éléments répétés dans un tableau
- Diviser un tableau en n-morceaux de taille
- Find éléments correspondants entre deux listes
- algorithme de Compression ( voir bloc-notes ) / codage de longueur D'exécution
- Groupement des lettres par la longueur, la touche de fonction ( voir notebook )
- valeurs consécutives au-dessus d'un seuil ( voir carnet )
- trouver des séries de numéros dans une liste ou produits continus (voir docs )
- trouver toutes les séquences connexes les plus longues
- prendre des séquences consécutives qui répondent à une condition ( voir post lié )
Note: plusieurs des ces derniers exemples proviennent du PyCon de Víctor Terrón (talk) 15191160920 "(Spanish) ," Kung Fu at Dawn with Itertools". Voir aussi le groupby
code source écrit en C.
Réponse
# OP: Yes, you can use `groupby`, e.g.
[do_something(list(g)) for _, g in groupby(lxml_elements, key=criteria_func)]
je voudrais donner un autre exemple où groupby sans tri ne fonctionne pas. Adapté de l'exemple de 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 " "
sortie est
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.
il y a deux groupes avec véhicule, alors qu'on ne peut s'attendre qu'à un seul groupe
@CaptSolo, j'ai essayé votre exemple, mais ça n'a pas marché.
from itertools import groupby
[(c,len(list(cs))) for c,cs in groupby('Pedro Manoel')]
sortie:
[('P', 1), ('e', 1), ('d', 1), ('r', 1), ('o', 1), (' ', 1), ('M', 1), ('a', 1), ('n', 1), ('o', 1), ('e', 1), ('l', 1)]
comme vous pouvez le voir, il y a deux o et deux e, mais ils se sont séparés. C'est alors que j'ai réalisé que vous aviez besoin de trier la liste passée à la fonction groupby. Ainsi, l'usage correct serait:
name = list('Pedro Manoel')
name.sort()
[(c,len(list(cs))) for c,cs in groupby(name)]
sortie:
[(' ', 1), ('M', 1), ('P', 1), ('a', 1), ('d', 1), ('e', 2), ('l', 1), ('n', 1), ('o', 2), ('r', 1)]
juste se rappeler, si la liste n'est pas triée, le fonction groupby ne fonctionnera pas !
comment utiliser les itértools de Python.groupby()?
vous pouvez utiliser groupby pour grouper des choses pour itérer. Vous donnez à groupby une fonction itérable, et une option clé fonction/appelable par laquelle vérifier les éléments comme ils sortent de l'itérable, et il retourne un itérateur qui donne un double-tuple du résultat de la clé appelable et les éléments réels dans un autre itérable. De l'aide:
groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).
voici un exemple de groupby en utilisant une coroutine pour grouper par un nombre, il utilise une clé callable (dans ce cas, coroutine.send
) pour simplement recracher le nombre Pour cependant de nombreuses itérations et un sous-itérateur groupé d'éléments: "15198090920"
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))
imprime
[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
tri et 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'}
un exemple utile que j'ai rencontré peut être utile:
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)
échantillon d'entrée: 14445221
sortie D'échantillon: (1,1) (3,4) (1,5) (2,2) (1,1)