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.

376
demandé sur jmunsch 2008-08-03 22:27:09

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.

543
répondu James Sulak 2015-12-04 08:51:07

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.

66
répondu Seb 2015-12-04 08:52:16

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.

34
répondu nimish 2017-08-08 10:01:05

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]
22
répondu user650654 2013-01-21 16:54:08

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.

18
répondu RussellStewart 2014-12-28 19:26:52

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

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)]
17
répondu pylang 2018-08-20 16:06:04

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

9
répondu octoback 2013-10-19 04:09:53

@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 !

6
répondu pedromanoel 2015-11-11 22:55:48

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])]
5
répondu Aaron Hall 2015-07-27 18:37:13

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'}
5
répondu Satyajit Das 2018-08-20 11:51:28

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)

1
répondu Arko 2017-06-18 17:16:54