Hogyan kell használni a Python itertools.groupby ()?

szavazat
364

Nem voltam képes megtalálni egy érthető magyarázata, hogy valójában a Python itertools.groupby()funkciót. Amit próbálok csinálni a következő:

  • Vegyünk egy listát - ebben az esetben a gyerekek a tárgyiasult lxmlelem
  • Osszuk alapján csoportokba néhány kritérium
  • Aztán később végighaladni ezen csoportok mindegyike külön-külön.

Átnéztem a dokumentációt , és a példát , de már volt baj próbál alkalmazni őket túl az egyszerű számok listája.

Szóval, hogyan lehet használni az itertools.groupby()? Van egy másik technika, amit érdemes használni? Mutatók jó „előfeltétele” olvasás is nyilvánvaló.

A kérdést 03/08/2008 19:27
a forrás felhasználó
Más nyelveken...                            


13 válasz

szavazat
523

Ahogy Sebastjan mondta, először meg kell rendezni az adatokat. Ez fontos.

Az I. rész nem értem, hogy a példában építési

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

ka jelenlegi csoportosítás kulcsot és gegy iterator, hogy tudod használni, hogy végighaladni a csoport által meghatározott, hogy csoportosulás gombot. Más szóval, a groupbybejáró maga visszatér iterátorokat.

Íme egy példa arra, hogy a világosabb változó nevét:

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

Ez megadja a kimenet:

Egy medve egy állat.
A kacsa egy állat.

A kaktusz egy növény.

A motorcsónak egy járművet.
A iskolabusz jármű.

Ebben a példában thingsegy lista sorok, ahol az első elem az egyes tuple csoport második elem tartozik.

A groupby()függvény két argumentuma: (1) Az adatok a csoporthoz, és (2) a funkció csoporthoz azt.

Itt lambda x: x[0]azt mondja groupby(), hogy az első tétel minden rekord a csoportosulás gombot.

A fenti forállítás, groupbyvisszatér három (kulcs, csoport bejáró) párban - egyszer minden egyedi kulcs. Használhatja a visszaadott iterator végighaladni egyes napirendi ebben a csoportban.

Itt egy kicsit más példát ugyanazokat az adatokat, egy lista megértés:

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

Ez megadja a kimenet:

állatok: medve és a kacsa.
növények: kaktusz.
járművek: motorcsónak és iskolabusz.

Válaszolt 10/08/2008 19:45
a forrás felhasználó

szavazat
65

Mutatsz a kódot?

A példa a Python docs nagyon egyszerű:

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

Tehát az Ön esetében, az adatok a csomópontok listáját, keyfunc, ahol a logika a kritériumoknak funkció megy majd groupby()csoportok az adatokat.

Óvatosnak kell lenned, hogy rendezni az adatokat a kritériumoknak, mielőtt hívja groupby, vagy nem fog működni. groupbymódszer valójában csak végigmegy a listán, és amikor a legfontosabb változásokat hoz létre egy új csoportot.

Válaszolt 03/08/2008 19:40
a forrás felhasználó

szavazat
32

A Neato trükk GroupBy hogy run length encoding egy sorban:

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

kapsz egy listát a 2-esek, ahol az első elem a char és a 2. is az ismétlések számát.

Edit: Megjegyzendő, hogy ez az, ami elválasztja itertools.groupbyaz SQL GROUP BYszemantika itertools nem (és általában nem) rendezni az iterátorhívásoknak előre, így csoportját azonos „kulcs” nem lesznek egyesítve.

Válaszolt 01/09/2008 00:27
a forrás felhasználó

szavazat
21

Egy másik példa:

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

eredmények

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

Vegye figyelembe, hogy igroup egy iterator (al-bejáró a dokumentáció nevezi).

Ez akkor hasznos, dobogó 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)

Egy másik példa a GroupBy - amikor a jelek nincsenek rendezve. A következő példában, db xx vannak csoportosítva értékek yy. Ebben az esetben egy sor nullákkal kerül kiadásra először, majd egy sor is, majd ismét egy sor nullákkal.

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

termel:

0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]
Válaszolt 21/01/2013 17:54
a forrás felhasználó

szavazat
17

FIGYELEM:

A szintaxis lista (GroupBy (...)) nem fog működni az utat, amit kíván. Úgy tűnik, hogy elpusztítsa a belső iterátor objektumokat, így segítségével

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

eredményezi:

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

Ehelyett a listán (GroupBy (...)), próbálja meg a [(k, listát (g)) k, g GroupBy (...)], vagy ha már így szintaxis gyakran,

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

és kap hozzáférést a GroupBy alkalmassága, elkerülve azokat a bosszantó (kis adat) bejárók együtt.

Válaszolt 16/11/2013 01:39
a forrás felhasználó

szavazat
11

itertools.groupby egy eszköz csoportosítására terméket.

Tól a docs , akkor gyűjtöget tovább mit tehet:

# [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 tárgyak hozam kulcs-csoport-párokat, ahol a csoport egy generátor.

Jellemzők

  • A. csoport egymást követő tételek együttesen (hasonló a unique_justseenrecept)
  • B. csoport összes előfordulását egy elemet, mivel rendezett iterable
  • C. Határozza meg, hogyan elemek csoportosítása egy gomb funkció

Az összehasonlítás

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

felhasználások

Több az utóbbi példák származó Víctor Terrón a PyCon talk (angol) (spanyol) , Kung Fu hajnalban Itertools . Akit érdekel, itt a forráskód a groupbyC nyelven írt

Válaszolt 25/08/2017 02:26
a forrás felhasználó

szavazat
10

Szeretnék egy másik példát, ahol GroupBy nélkül rendezés nem működik. Átvéve például 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 " "

kimenet

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.

két csoportban vehicule, mivel ez várható is csak egy csoport

Válaszolt 07/05/2013 21:09
a forrás felhasználó

szavazat
7

@CaptSolo, megpróbáltam a példát, de ez nem működött.

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

output:

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

Mint látható, két o és két e-é, de kaptak külön csoportokba. Ez az, amikor rájöttem, meg kell rendezni a listát át a GroupBy funkciót. Tehát a helyes használat lenne:

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

output:

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

Csak emlékezve, ha a lista nincs rendezve, a GroupBy funkció nem fog működni !

Válaszolt 15/10/2009 16:41
a forrás felhasználó

szavazat
5

Hogyan kell használni a Python itertools.groupby ()?

Használhatja GroupBy csoportba dolgokat végighaladni. Adsz GroupBy egy iterable és opcionális kulcs funkció / lehívható, amellyel ellenőrizni a terméket, ahogy jönnek ki a iterable, és visszatér egy iterátor, hogy ad egy két-est az eredmény a legfontosabb lehívható és a tényleges tételek egy másik iterable. A segítség:

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

Íme egy példa GroupBy egy coroutine csoporthoz egy számot, ez egy kulcsot használ lehívható (ebben az esetben coroutine.send), hogy csak kiköp a gróf azonban sok iteráció és a csoportosított al-bejáró elemei:

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

nyomatok

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
Válaszolt 27/07/2015 18:06
a forrás felhasználó

szavazat
3

Válogató és 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'}
Válaszolt 01/08/2017 07:14
a forrás felhasználó

szavazat
2

Egy hasznos példa, hogy rátaláltam hasznos lehet:

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)

Minta bemenet: 14445221

Minta kimeneti: (1,1) (3,4) (1,5) (2,2) (1,1)

Válaszolt 18/06/2017 17:16
a forrás felhasználó

szavazat
1

Írhat saját GroupBy funkció:

           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]}
Válaszolt 10/10/2018 17:53
a forrás felhasználó

szavazat
-1

Készíts egy bejáró, amely visszaadja egymást követő kulcsokat és csoportoknak a iterable. A kulcs egy függvény számítási kulcs-érték minden egyes eleme.

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
Válaszolt 23/08/2018 06:44
a forrás felhasználó

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