Comment puis-je utiliser le itertools.groupby de Python ()?

voix
364

Je ne l' ai pas été en mesure de trouver une explication compréhensible de l'utilisation de Python en fait itertools.groupby()la fonction. Ce que je suis en train de faire est la suivante:

  • Faites une liste - dans ce cas, les enfants d'un objectivé lxmlélément
  • Diviser en groupes en fonction de certains critères
  • Puis, plus tard itérer sur chacun de ces groupes séparément.

J'ai passé en revue la documentation et les exemples , mais je l' ai eu du mal à essayer de les appliquer au - delà d' une simple liste de numéros.

Alors, comment puis-je utiliser des itertools.groupby()? Y at - il une autre technique que je devrais utiliser? Pointeurs à une bonne lecture « prérequis » seraient également appréciées.

Créé 03/08/2008 à 19:27
source utilisateur
Dans d'autres langues...                            


13 réponses

voix
523

Comme l'a dit Sebastjan, vous devez d' abord trier vos données. C'est important.

La partie que je n'ai pas est que, dans la construction d'exemple

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
   groups.append(list(g))    # Store group iterator as a list
   uniquekeys.append(k)

kest la clé de regroupement en cours, et gest un itérateur que vous pouvez utiliser pour itérer sur le groupe défini par cette clé de regroupement. En d' autres termes, le groupbyiterator se retourne itérateurs.

Voici un exemple de cela, en utilisant les noms de variables plus claires:

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 à moteur est un véhicule.
Un autobus scolaire est un véhicule.

Dans cet exemple, thingsune liste de tuples , où le premier élément de chaque tuple est le groupe le deuxième article appartient.

La groupby()fonction prend deux arguments: (1) les données de groupe et (2) la fonction de groupe avec.

Ici, lambda x: x[0]dit groupby()d'utiliser le premier élément de chaque tuple comme la clé de regroupement.

Dans ce qui précède la fordéclaration, groupbyretourne trois paires (clé, groupe iterator) - une fois pour chaque clé unique. Vous pouvez utiliser le itérateur retourné à 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 compréhension de la liste:

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 le canard.
plantes: cactus.
véhicules: bateau à moteur et autobus scolaire.

Créé 10/08/2008 à 19:45
source utilisateur

voix
65

Pouvez-vous nous montrer votre code?

L'exemple sur les docs Python 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, les données sont une liste de nœuds, keyfunc est où la logique de votre fonction de critères va et puis des groupby()groupes les données.

Vous devez faire attention à trier les données en fonction des critères avant d'appeler groupbyou cela ne fonctionnera pas. groupbyméthode fait juste itère à travers une liste et chaque fois que les principaux changements qu'elle crée un nouveau groupe.

Créé 03/08/2008 à 19:40
source utilisateur

voix
32

Une astuce neato avec groupby consiste à exécuter un codage de longueur dans une ligne:

[(c,len(list(cgen))) for c,cgen in groupby(some_string)]

vous donnera une liste de 2-tuples où le premier élément est le charbon et le 2ème est le nombre de répétitions.

Edit: Notez que c'est ce qui sépare itertools.groupbyde la SQL GROUP BYsémantique: itertools ne dispose pas (et en général ne peut pas) trier l'itérateur à l' avance, afin que les groupes avec le même « clé » ne sont pas fusionnés.

Créé 01/09/2008 à 00:27
source utilisateur

voix
21

Un autre exemple:

for key, igroup in itertools.groupby(xrange(12), lambda x: x // 5):
    print key, list(igroup)

résulte en

0 [0, 1, 2, 3, 4]
1 [5, 6, 7, 8, 9]
2 [10, 11]

Notez que igroup est un iterator (un sous-iterator que la documentation appelle).

Ceci est utile pour Chunking 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 touches ne sont pas triés. Dans l'exemple suivant, les éléments xx sont groupés par les valeurs yy. Dans ce cas, un ensemble de zéros est la première sortie, suivi d'un ensemble de ceux, à nouveau suivi 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]
Créé 21/01/2013 à 17:54
source utilisateur

voix
17

ATTENTION:

La liste de syntaxe (groupby (...)) ne fonctionneront pas la façon dont vous avez l'intention. Il semble détruire les objets itérateurs internes, donc l'utilisation

for x in list(groupby(range(10))):
    print(list(x[1]))

produira:

[]
[]
[]
[]
[]
[]
[]
[]
[]
[9]

Au lieu de cela, de la liste (groupby (...)), essayez [(k, liste (g)) pour k, g groupby (...)], ou si vous utilisez cette syntaxe souvent,

def groupbylist(*args, **kwargs):
    return [(k, list(g)) for k, g in groupby(*args, **kwargs)]

et avoir accès à la fonctionnalité groupby tout en évitant ces satanés (pour les petites données) itérateurs tous ensemble.

Créé 16/11/2013 à 01:39
source utilisateur

voix
11

itertools.groupby est un outil pour regrouper les éléments.

De la documentation , nous glaner encore 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 les objets donnent des paires du groupe clé où le groupe est un générateur.

Caractéristiques

  • A. Groupe des éléments consécutifs ensemble (semblable à la unique_justseenrecette)
  • B. Groupe toutes les occurrences d'un élément, donné une itérables triée
  • C. Spécifier comment les éléments groupe 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
>>> 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']

Les usages

Plusieurs de ces derniers exemples dérivent de PyCon discours de Víctor Terron ( en anglais) (espagnol) , Kung Fu à l' aube avec itertools . Pour toute personne intéressée, voici le code source pour groupbyécrit en C.

Créé 25/08/2017 à 02:26
source utilisateur

voix
10

Je voudrais donner un autre exemple où groupby sans tri ne fonctionne pas. Adapté de l'exemple par 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 que l'on pouvait attendre un seul groupe

Créé 07/05/2013 à 21:09
source utilisateur

voix
7

@CaptSolo, j'ai essayé votre exemple, mais il ne fonctionne pas.

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 de O et deux e, mais ils se sont séparés en groupes. C'est quand j'ai réalisé que vous devez trier la liste transmise à la fonction groupby. Alors, serait l'utilisation correcte:

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)]

Il suffit de se rappeler, si la liste ne sont pas triées, la fonction groupby ne fonctionnera pas !

Créé 15/10/2009 à 16:41
source utilisateur

voix
5

Comment puis-je utiliser le itertools.groupby de Python ()?

Vous pouvez utiliser groupby aux choses du groupe à itérer. Vous donnez groupby un itératives, et une option clé fonction / appelable permettant de vérifier les éléments qu'ils sortent de la itératives, et il renvoie un itérateur qui donne deux tuples du résultat de la appelable clé et les éléments réels dans un autre itérables. 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 un coroutine au groupe par un compte, il utilise une clé appelable (dans ce cas, coroutine.send) juste cracher le nombre d'itérations pour cependant et un sous-iterator regroupés d'éléments:

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))

estampes

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
Créé 27/07/2015 à 18:06
source utilisateur

voix
3

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'}
Créé 01/08/2017 à 07:14
source utilisateur

voix
2

Un exemple utile que je suis tombé 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)

entrée échantillon: 14445221

Exemple de sortie: (1,1) (3,4) (1,5) (2,2) (1,1)

Créé 18/06/2017 à 17:16
source utilisateur

voix
1

Vous pouvez écrire propre fonction 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]}
Créé 10/10/2018 à 17:53
source utilisateur

voix
-1

Faire une iterator qui retourne les clés consécutives et les groupes de la itérables. La clé est une fonction de calcul d'une valeur de clé pour chaque élément.

import itertools

for k,group in  itertools.groupby([['subject1','english'],['subject2','kannada']]):
for g in group:
    print(f'{k[0]} is {g[1]}')
# output : 
subject1 is english
subject2 is kannada
Créé 23/08/2018 à 06:44
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more