Come faccio a usare itertools.groupby di Python ()?

voti
364

Non sono stato in grado di trovare una spiegazione comprensibile di come utilizzare effettivamente di Python itertools.groupby()funzione. Quello che sto cercando di fare è questo:

  • Fate una lista - in questo caso, i figli di un oggettivato lxmlelemento
  • Dividerlo in gruppi in base a determinati criteri
  • Poi più tardi iterare su ciascuno di questi gruppi separatamente.

Ho rivisto la documentazione e gli esempi , ma ho avuto problemi cercando di applicarle al di là di un semplice elenco di numeri.

Così, come si usa di itertools.groupby()? Esiste un'altra tecnica dovrei usare? Puntatori a buona lettura prerequisito sarebbe anche apprezzato.

È pubblicato 03/08/2008 alle 17:27
fonte dall'utente
In altre lingue...                            


13 risposte

voti
65

Ci puoi mostrare il tuo codice?

L'esempio alla documentazione Python è molto semplice:

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

Quindi nel tuo caso, i dati è una lista di nodi, keyfunc è dove la logica della vostra funzione criteri va e poi groupby()gruppi di dati.

È necessario fare attenzione a ordinare i dati in base ai criteri prima di chiamare groupbyo non funzionerà. groupbymetodo in realtà solo scorre un elenco e ogni volta che i cambiamenti chiave che crea un nuovo gruppo.

Risposto il 03/08/2008 a 17:40
fonte dall'utente

voti
523

Come ha detto Sebastjan, dovete prima di ordinare i dati. Questo è importante.

La parte non ho avuto è che nell'esempio di costruzione

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

kè la chiave di raggruppamento corrente, ed gè un iteratore che è possibile utilizzare per iterare il gruppo definito da quella chiave di raggruppamento. In altre parole, l' groupbyiteratore si ritorna iteratori.

Ecco un esempio di che, utilizzando i nomi delle variabili più chiare:

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

Questo vi darà l'output:

Un orso è un animale.
Un'anatra è un animale.

Un cactus è una pianta.

Una barca di velocità è un veicolo.
Uno scuolabus è un veicolo.

In questo esempio, thingsè una lista di tuple in cui il primo elemento in ogni tupla è il gruppo il secondo elemento appartiene.

La groupby()funzione prende due argomenti: (1) i dati al gruppo e (2) la funzione di gruppo con.

Qui, lambda x: x[0]dice groupby()di utilizzare il primo elemento in ogni tupla come chiave di raggruppamento.

In precedenza forcomunicato, groupbyrestituisce tre coppie (chiave, gruppo iteratore) - una volta per ogni chiave unica. È possibile utilizzare l'iteratore tornato a iterare su ogni singolo elemento in quel gruppo.

Ecco un esempio leggermente diverso con gli stessi dati, utilizzando una lista di comprensione:

for key, group in groupby(things, lambda x: x[0]):
    listOfThings = " and ".join([thing[1] for thing in group])
    print key + "s:  " + listOfThings + "."

Questo vi darà l'output:

animali: orso e anatra.
piante: cactus.
veicoli: barca di velocità e scuolabus.

Risposto il 10/08/2008 a 17:45
fonte dall'utente

voti
32

Un trucco neato con groupby è di eseguire la codifica lunghezza in una riga:

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

vi darà un elenco di 2-tuple in cui il primo elemento è il carattere e il 2 ° è il numero di ripetizioni.

Edit: Si noti che questo è ciò che separa itertools.groupbyda SQL GROUP BYsemantica: itertools non lo fa (e, in generale, non può) ordinare l'iteratore in anticipo, in modo da gruppi con lo stesso "chiave" non sono fuse.

Risposto il 31/08/2008 a 22:27
fonte dall'utente

voti
7

@CaptSolo, ho provato il vostro esempio, ma non ha funzionato.

from itertools import groupby 
[(c,len(list(cs))) for c,cs in groupby('Pedro Manoel')]

Produzione:

[('P', 1), ('e', 1), ('d', 1), ('r', 1), ('o', 1), (' ', 1), ('M', 1), ('a', 1), ('n', 1), ('o', 1), ('e', 1), ('l', 1)]

Come si può vedere, ci sono due O e due e di, ma hanno ottenuto in gruppi separati. Questo è quando mi sono reso conto è necessario ordinare l'elenco passato alla funzione GroupBy. Quindi, l'uso corretto sarebbe:

name = list('Pedro Manoel')
name.sort()
[(c,len(list(cs))) for c,cs in groupby(name)]

Produzione:

[(' ', 1), ('M', 1), ('P', 1), ('a', 1), ('d', 1), ('e', 2), ('l', 1), ('n', 1), ('o', 2), ('r', 1)]

Basta ricordare, se l'elenco non è ordinato, la funzione GroupBy non funzionerà !

Risposto il 15/10/2009 a 14:41
fonte dall'utente

voti
21

Un altro esempio:

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

risultati in

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

Si noti che igroup è un iteratore (un sotto-iteratore come la documentazione chiama).

Questo è utile per chunking un generatore:

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 altro esempio di groupby - quando i pulsanti non sono ordinati. Nel seguente esempio, gli articoli di xx sono raggruppate per valori yy. In questo caso, una serie di zeri viene emesso prima, seguita da un gruppo di pile, seguita nuovamente da una serie di zeri.

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]
Risposto il 21/01/2013 a 14:54
fonte dall'utente

voti
10

Vorrei dare un altro esempio in cui groupby senza sorta non funziona. Adattato da esempio da 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 " "

uscita è

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.

ci sono due gruppi con vehicule, mentre ci si potrebbe aspettare un solo gruppo

Risposto il 07/05/2013 a 19:09
fonte dall'utente

voti
17

AVVERTIMENTO:

La lista di sintassi (groupby (...)) non funziona il modo in cui si intende. Sembra di distruggere gli oggetti iteratore interni, in modo da utilizzare

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

produrrà:

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

Invece, di lista (groupby (...)), provare [(k, la lista (g)) per k, g in GroupBy (...)], o se si utilizza la sintassi che spesso,

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

e ottenere l'accesso alle funzionalità groupby evitando quei fastidiosi (per piccolo dati) iteratori tutti insieme.

Risposto il 15/11/2013 a 22:39
fonte dall'utente

voti
5

Come faccio a usare itertools.groupby di Python ()?

È possibile utilizzare groupby alle cose di gruppo per iterare. Tu dai GroupBy un iterabile, e un optional chiave funzione / callable con cui controllare le voci come vengono fuori dal iterabile, e restituisce un iteratore che dà un due tuple del risultato della chiave callable e gli elementi reali in un'altra iterabile. Da l'aiuto:

groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).

Ecco un esempio di groupby utilizzando un coroutine di gruppo da un conteggio, si utilizza una chiave richiamabile (in questo caso, coroutine.send) ad appena sputare il conteggio per tuttavia molte iterazioni e un raggruppate sotto-iteratore di elementi:

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

stampe

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
Risposto il 27/07/2015 a 17:06
fonte dall'utente

voti
2

Un esempio utile che mi sono imbattuto in possono essere utili:

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)

input di esempio: 14445221

Esempio di output: (1,1) (3,4) (1,5) (2,2) (1,1)

Risposto il 18/06/2017 a 16:16
fonte dall'utente

voti
3

Ordinamento e 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'}
Risposto il 01/08/2017 a 06:14
fonte dall'utente

voti
11

itertools.groupby è uno strumento per elementi di raggruppamento.

Da documenti , abbiamo Spigoliamo ulteriormente ciò che si potrebbe fare:

# [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 oggetti producono coppie chiave del gruppo cui il gruppo è un generatore.

Caratteristiche

  • A. Gruppo elementi consecutivi insieme (simile alla unique_justseenricetta)
  • B. Gruppo tutte le occorrenze di un elemento, dato un iterabile ordinato
  • C. Specificare come raggruppare oggetti con una funzione chiave

confronti

# 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']

usi

Molti degli ultimi esempi derivano da PyCon discorso di Víctor Terrón (Inglese) (spagnolo) , Kung Fu all'alba con itertools . Per chiunque sia interessato, ecco il codice sorgente per groupbyscritto in C.

Risposto il 25/08/2017 a 01:26
fonte dall'utente

voti
-1

Crea un iteratore che restituisce chiavi e gruppi consecutivi da iterable. La chiave è una funzione che calcola un valore chiave per ogni elemento.

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
Risposto il 23/08/2018 a 05:44
fonte dall'utente

voti
1

È possibile scrivere una propria funzione 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]}
Risposto il 10/10/2018 a 16:53
fonte dall'utente

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