Jak mohu použít Python itertools.groupby ()?

hlasů
364

Nebyl jsem schopen najít srozumitelné vysvětlení toho, jak se vlastně používat Python itertools.groupby()funkci. Co se snažím udělat, je toto:

  • Vezměte seznam - v tomto případě děti jako objektivizovaného lxmlprvku
  • Rozdělit do skupin na základě určitých kritérií
  • Později iteraci přes každé z těchto skupin samostatně.

Prohlédli jsme si dokumentaci a příklady , ale já jsem měl problémy se snaží aplikovat je nad rámec pouhého seznamu čísel.

Tak, jak mohu použít na itertools.groupby()? Je tu další techniku bych měl používat? Ukazatele na dobré „předpoklad“, čtení by také ocenil.

Položena 03/08/2008 v 19:27
zdroj uživatelem
V jiných jazycích...                            


13 odpovědí

hlasů
523

Jak již bylo řečeno Sebastjan, musíte nejprve vyřešit vaše data. Toto je důležité.

Část Nedostal jsem je, že v příkladu výstavby

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

kje aktuální seskupení klíč a gje iterátor, který můžete použít k iteraci přes skupiny vymezené podle tohoto seskupení klíče. Jinými slovy, groupbyiterátor sám vrací iterátory.

Zde je příklad toho, že při použití jasnější názvy proměnných:

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

To vám dá výstup:

Medvěd je zvíře.
Kachna je zvíře.

Kaktus je rostlina.

Rychlostní člun je vozidlo.
Školní autobus je vozidlo.

V tomto příkladu thingsje seznam n-tic, kde první položka v každém n-tice je skupina druhá položka patří.

groupby()Funkce má dva argumenty: (1) data do skupiny, a (2), na funkci skupina, s.

Zde se lambda x: x[0]říká, groupby()použít na první položku v každém n-tice jako klíč seskupení.

Ve výše uvedeném forprohlášení, groupbyvrátí tři (key, skupina iterator) párů - jednou pro každý jedinečný klíč. Můžete použít vrácený iterátor iterovat přes jednotlivé položky v dané skupině.

Zde je trochu jiný příklad se stejnými daty, pomocí seznamu s porozuměním:

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

To vám dá výstup:

zvířata: medvěd a kachna.
Rostliny: kaktus.
Vozidla: rychlost lodi a školní autobus.

Odpovězeno 10/08/2008 v 19:45
zdroj uživatelem

hlasů
65

Můžete nám ukázat svůj kód?

V příkladu na Python dokumenty je velmi jednoduchý:

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

Takže ve vašem případě, dat je seznam uzlů, keyfunc je místo, kde logika vaší funkce kritérií jde a pak groupby()seskupuje data.

Musíte dávat pozor, aby třídit data podle kritérií, než zavoláte groupby, nebo to nebude fungovat. groupbyMetoda vlastně jen projde seznamu a kdykoliv klíčové změny, které vytvoří novou skupinu.

Odpovězeno 03/08/2008 v 19:40
zdroj uživatelem

hlasů
32

Neato trik se groupby je spustit kódování délky v jednom řádku:

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

vám dát seznam 2-tic, kde první prvek je char a druhý je počet opakování.

Edit: Všimněte si, že to je to, co odděluje itertools.groupbyod SQL GROUP BYsémantiky: itertools není (a obecně nemohou) řadit iterátor v předstihu, takže skupin se stejnou „klíč“ nejsou sloučeny.

Odpovězeno 01/09/2008 v 00:27
zdroj uživatelem

hlasů
21

Další příklad:

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

následek

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

Všimněte si, že igroup je iterátor (a sub-iterátor jako dokumentace ji nazývá).

To je užitečné pro Chunking generátor:

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)

Dalším příkladem groupby - pokud jsou klávesy nejsou seřazeny. V následujícím příkladu, položky v xx jsou seskupeny podle hodnoty v rr. V tomto případě, jeden soubor nul je vysílán jako první, následovaná řadou ty, následuje opět sadou nul.

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

vyrábí:

0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]
Odpovězeno 21/01/2013 v 17:54
zdroj uživatelem

hlasů
17

VAROVÁNÍ:

Seznam syntaxe (groupby (...)) nebude fungovat tak, že máte v úmyslu. Zdá se, že ke zničení vnitřních objektů Iterator, takže s použitím

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

bude vyrábět:

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

Místo toho, ze seznamu (groupby (...)), zkuste [(k, seznam (g)) k K, G v groupby (...)], nebo chcete-li použít tuto syntaxi často,

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

a získat přístup k funkcím groupby aniž by ty otravné (pro malé dat) iterátory dohromady.

Odpovězeno 16/11/2013 v 01:39
zdroj uživatelem

hlasů
11

itertools.groupby je nástroj pro seskupování položek.

Z docs jsme sbírat dál, co by to mohlo udělat:

# [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 Objekty se získá klíčový skupina párů, kde skupina je generátor.

Funkce

  • A. Skupina po sobě jdoucích položek dohromady (podobně jako unique_justseenrecept)
  • B. Skupina všechny výskyty položky, daný tříděný iterable
  • C. Určete, jak se skupina předmětů s funkční klávesou

porovnání

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

použití

Některé z posledních příkladů odvodit od Víctor Terron je PyCon diskuse (anglicky) (španělština) , Kung Fu za úsvitu s Itertools . Pro zájemce, tady je zdrojový kód pro groupbynapsaný v jazyce C.

Odpovězeno 25/08/2017 v 02:26
zdroj uživatelem

hlasů
10

Chtěl bych dát jiný příklad, kdy groupby bez takového nefunguje. Převzato z příkladu James Šulák

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

výstupem je

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.

existují dvě skupiny s vehikula, přičemž by se dalo očekávat, že pouze jedna skupina

Odpovězeno 07/05/2013 v 21:09
zdroj uživatelem

hlasů
7

@CaptSolo, Zkoušel jsem váš příklad, ale nefungovalo to.

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

Výstup:

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

Jak můžete vidět, jsou zde dvě o a dvě e to, ale oni se dostali do samostatných skupin. To je, když jsem si uvědomil, co potřebujete, aby třídit seznam předaný funkci groupby. Takže správné použití by bylo:

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

Výstup:

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

Jen si pamatovat, je-li seznam netřídí, funkce groupby nebude fungovat !

Odpovězeno 15/10/2009 v 16:41
zdroj uživatelem

hlasů
5

Jak mohu použít Python itertools.groupby ()?

Můžete použít groupby do skupiny věcí iteraci. Dáte groupby iterable a volitelná klávesa funkce / callable kterou ke kontrole položky, jak vyjdou z iterable, a vrací iterátor, který dává dva-tice o výsledku klíč callable a skutečných kusů dalším iterable. Od pomoci:

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

Zde je příklad groupby pomocí Coroutine pro skupinu podle počtu, používá klíčový callable (v tomto případě coroutine.send) jen vyplivnout počtu vztahujícího se k však mnoho iterací a seskupené sub-iterace prvků:

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

tisky

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
Odpovězeno 27/07/2015 v 18:06
zdroj uživatelem

hlasů
3

Třídění a 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'}
Odpovězeno 01/08/2017 v 07:14
zdroj uživatelem

hlasů
2

Jeden užitečný příklad, který jsem narazil mohou být užitečné:

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)

Vzorek vstup: 14445221

Ukázkový výstup: (1,1) (3,4) (1,5) (2,2) (1,1)

Odpovězeno 18/06/2017 v 17:16
zdroj uživatelem

hlasů
1

Můžete napsat vlastní groupby funkce:

           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]}
Odpovězeno 10/10/2018 v 17:53
zdroj uživatelem

hlasů
-1

Udělat iterátor, který se vrací po sobě jdoucích klíče a skupin z iterable. Klíč je funkce výpočtu klíče hodnoty pro každý prvek.

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
Odpovězeno 23/08/2018 v 06:44
zdroj uživatelem

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