Hoe kan ik de Python's itertools.groupby () gebruiken?

stemmen
364

Ik ben niet in staat om een begrijpelijke uitleg over hoe Python's daadwerkelijk gebruik kunnen vinden itertools.groupby()functie. Wat ik probeer te doen is het volgende:

  • Neem een lijst - in dit geval, de kinderen van een geobjectiveerde lxmlelement
  • Verdeel het in groepen op basis van een aantal criteria
  • Later itereren over elk van deze groepen afzonderlijk.

Ik heb beoordeeld de documentatie en de voorbeelden , maar ik heb moeite proberen om ze toe te passen dan een eenvoudige lijst met nummers gehad.

Dus, hoe kan ik het gebruik van itertools.groupby()? Is er een andere techniek die ik zou moeten gebruiken? Verwijzingen naar goed voorwaarde te lezen zou ook gewaardeerd worden.

De vraag is gesteld op 03/08/2008 om 19:27
bron van user
In andere talen...                            


13 antwoorden

stemmen
65

Kunt u ons uw code?

Het voorbeeld van de Python documentatie is heel eenvoudig:

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

Dus in jouw geval, gegevens is een lijst van knooppunten, keyfunc is waar de logica van uw criteria functie gaat en vervolgens groupby()de gegevens groepen.

Je moet voorzichtig zijn de gegevens te sorteren volgens de criteria voordat u belt groupbyof het zal niet werken. groupbymethode eigenlijk gewoon doorloopt een lijst en wanneer de belangrijkste veranderingen die het creëert een nieuwe groep.

antwoordde op 03/08/2008 om 19:40
bron van user

stemmen
523

Zoals Sebastjan gezegd, moet u eerst uw gegevens te sorteren. Dit is belangrijk.

Het deel ik niet krijg, is dat in het voorbeeld bouw

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

kis de huidige groepering sleutel, en gis een iterator die u kunt gebruiken om itereren over de groep, die op die groep te drukken. Met andere woorden, de groupbyiterator zelf terug iterators.

Hier is een voorbeeld van die, met behulp van duidelijkere namen van variabelen:

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

Dit geeft u de output te geven:

Een beer is een dier.
Een eend is een dier.

Een cactus is een plant.

Een speedboot is een voertuig.
Een schoolbus is een voertuig.

In dit voorbeeld, thingsis een lijst van tupels waarbij het eerste item in elke tupel de groep tweede punt behoort.

De groupby()functie heeft twee argumenten: (1) de gegevens te groeperen en (2) de functie groep met.

Hier, lambda x: x[0]vertelt groupby()het eerste item te gebruiken in elke tupel als de combinatie sleutel.

In de bovenstaande forverklaring, groupbygeeft drie (key, groep iterator) paren - een keer voor elke unieke sleutel. U kunt de teruggekeerde iterator te gebruiken om te herhalen elk afzonderlijk item in die groep.

Hier is een iets ander voorbeeld met dezelfde gegevens, met behulp van een lijst begrip:

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

Dit geeft u de output te geven:

dieren: draag en eend.
planten: cactus.
voertuigen: speedboot en schoolbus.

antwoordde op 10/08/2008 om 19:45
bron van user

stemmen
32

Een neato truc met GroupBy is lengtecodering reeks in één lijn:

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

krijgt u een lijst van 2-tupels te geven waar het eerste element is de char en de 2e is het aantal herhalingen.

Edit: Let op: dit is wat scheidt itertools.groupbyvan de SQL- GROUP BYsemantiek: itertools niet (en in het algemeen niet) sorteren iterator van tevoren, dus groepen met dezelfde "sleutel" worden niet samengevoegd.

antwoordde op 01/09/2008 om 00:27
bron van user

stemmen
7

@CaptSolo, probeerde ik uw voorbeeld, maar het werkte niet.

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

Zoals u kunt zien, zijn er twee o's en twee e's, maar ze kregen in afzonderlijke groepen. Dat is toen ik me realiseerde je nodig hebt om de lijst doorgegeven aan de GroupBy functie sorteren. Dus, zou het correcte gebruik zijn:

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

Net herinneren, als de lijst niet wordt gesorteerd, de GroupBy functie zal niet werken !

antwoordde op 15/10/2009 om 16:41
bron van user

stemmen
21

Een ander voorbeeld:

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

resulteert in

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

Merk op dat iGroup is een iterator (een sub-iterator als de documentatie noemt).

Dit is handig voor chunking een generator:

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)

Een ander voorbeeld van GroupBy - wanneer de toetsen niet worden gesorteerd. In het volgende voorbeeld worden items in xx gegroepeerd waarden yy. In dit geval is één stel nullen wordt uitgevoerd, gevolgd door een reeks van enen, opnieuw gevolgd door een reeks nullen.

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

produceert:

0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]
antwoordde op 21/01/2013 om 17:54
bron van user

stemmen
10

Ik wil graag een ander voorbeeld waar GroupBy zonder soort niet werkt geven. Aangepast van bijvoorbeeld door 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 " "

output is

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.

Er zijn twee groepen voertuig, terwijl slechts één groep zou kunnen verwachten

antwoordde op 07/05/2013 om 21:09
bron van user

stemmen
17

WAARSCHUWING:

De syntaxis lijst (GroupBy (...)) zal de manier waarop u van plan bent niet werken. Het lijkt de interne iterator voorwerpen te vernietigen, zodat het gebruik van

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

zal produceren:

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

In plaats van de lijst (GroupBy (...)), probeer dan [(k, lijst (g)) voor k, g in GroupBy (...)], of als u dat syntax maken vaak gebruik van,

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

en krijg toegang tot de GroupBy functionaliteit, terwijl het vermijden van die vervelende (voor kleine gegevens) iteratoren allemaal samen.

antwoordde op 16/11/2013 om 01:39
bron van user

stemmen
5

Hoe kan ik de Python's itertools.groupby () gebruiken?

U kunt gebruik maken GroupBy groeperen dingen om over te herhalen. Je geeft GroupBy een iterable, en een optionele belangrijke functie / callable waarmee de items te controleren als ze uit de iterable komen, en keert terug een iterator die een twee-tupel van het resultaat van de belangrijkste callable en de feitelijke items in geeft andere Iterable. Van de hulp:

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

Hier is een voorbeeld van GroupBy met behulp van een coroutine te groeperen op een telling, het maakt gebruik van een sleutel callable (in dit geval coroutine.send) om gewoon spugen de telling voor hoeveel iteraties en een gegroepeerde sub-iterator van de elementen:

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

prints

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
antwoordde op 27/07/2015 om 18:06
bron van user

stemmen
2

Een goed voorbeeld dat ik tegenkwam kan nuttig zijn:

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)

Voorbeeldinvoer: 14445221

Voorbeelduitvoer: (1,1) (3,4) (1,5) (2,2) (1,1)

antwoordde op 18/06/2017 om 17:16
bron van user

stemmen
3

Sorteren en 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'}
antwoordde op 01/08/2017 om 07:14
bron van user

stemmen
11

itertools.groupby is een hulpmiddel voor het groeperen van items.

Uit de documentatie , verzamelen we verder wat het zou kunnen doen:

# [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 voorwerpen opbrengst key-groepsparen waarbij de groep een generator.

Kenmerken

  • A. Group opeenvolgende items bij elkaar (vergelijkbaar met het unique_justseenrecept)
  • B. Groep alle voorkomens van een item, gegeven een gesorteerde iterable
  • C. Geef aan hoe om items te groeperen met een sleutel functie

vergelijkingen

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

Toepassingen

Een aantal van de laatste voorbeelden ontlenen Víctor Terrón's PyCon talk (Engels) (Spaans) , Kung Fu in Dawn met itertools . Voor iedereen die geïnteresseerd is, hier is de broncode voor groupbygeschreven in C.

antwoordde op 25/08/2017 om 02:26
bron van user

stemmen
-1

Maak een iterator die opeenvolgende sleutels en groepen terug uit de iterable. De sleutel is een functie berekenen van een sleutelwaarde voor elk element.

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
antwoordde op 23/08/2018 om 06:44
bron van user

stemmen
1

U kunt eigen GroupBy functie schrijven:

           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]}
antwoordde op 10/10/2018 om 17:53
bron van user

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