Hvordan bruker jeg Pythons itertools.groupby ()?

stemmer
369

Jeg har ikke vært i stand til å finne en forståelig forklaring på hvordan du faktisk bruke Pythons itertools.groupby()funksjon. Det jeg prøver å gjøre er dette:

  • Ta en liste - i dette tilfellet, barn av en objektivert lxmlelement
  • Dele det inn i grupper basert på noen kriterier
  • Senere iterere over hver av disse gruppene hver for seg.

Jeg har vurdert dokumentasjonen , og eksemplene , men jeg har hatt problemer med å prøve å bruke dem utover en enkel liste med tall.

Så, hvordan bruker jeg av itertools.groupby()? Er det en annen teknikk jeg skal bruke? Pekere til god forutsetning lesing vil også bli verdsatt.

Publisert på 03/08/2008 klokken 18:27
kilden bruker
På andre språk...                            


13 svar

stemmer
536

Som Sebastjan sagt, må du først sortere dataene. Dette er viktig.

Den delen jeg ikke får er at i eksempelet bygge

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

ker gjeldende gruppering nøkkelen, og ger en iterator som du kan bruke til å iterere over gruppe som er definert ved at gruppering nøkkelen. Med andre ord, det groupbyiterator seg tilbake iteratorer.

Her er et eksempel på det, ved hjelp klarere variabelnavn:

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

Dette vil gi deg resultatet:

En bjørn er et dyr.
En and er et dyr.

En Cactus er en plante.

En speedbåt er et kjøretøy.
En skolebuss er et kjøretøy.

I dette eksemplet, thingser en liste av tuppeler der det første elementet i hver tuppel er gruppen det andre elementet tilhører.

Den groupby()funksjonen tar to argumenter: (1) data til-gruppe og (2) den funksjon å gruppere den med.

Her lambda x: x[0]forteller groupby()bruke det første elementet i hver tuppel som gruppering nøkkelen.

I de ovennevnte forutsagn, groupbyreturnerer tre (nøkkel, gruppe parene iteratorknapper) - en gang for hver unik nøkkel. Du kan bruke den returnerte iterator å iterere over hvert enkelt element i den gruppen.

Her er en litt annen eksempel med de samme dataene, ved hjelp av en liste forståelse:

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

Dette vil gi deg resultatet:

dyr: bjørn og duck.
planter: kaktus.
biler: speedbåt og skolebuss.

Svarte 10/08/2008 kl. 18:45
kilden bruker

stemmer
66

Kan du vise oss koden din?

Eksempelet på Python docs er ganske enkel:

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

Så i ditt tilfelle, er data en liste over noder, er keyfunc hvor logikken i din kriteriene funksjon går og deretter groupby()grupper dataene.

Du må være forsiktig med å sortere dataene etter kriteriene før du ringer groupbyeller det vil ikke fungere. groupbymetoden faktisk bare gjentas gjennom en liste og når de viktigste endringene det skaper en ny gruppe.

Svarte 03/08/2008 kl. 18:40
kilden bruker

stemmer
34

En neato kunsten med groupby er til kjørelengdekoding på en linje:

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

vil gi deg en liste over 2-tupler hvor det første elementet er røye og andre er antall repetisjoner.

Edit: Merk at dette er det som skiller itertools.groupbyfra SQL- GROUP BYsemantikk: itertools ikke (og generelt ikke kan) sortere iterator på forhånd, slik at grupper med samme "nøkkelen" er ikke slått sammen.

Svarte 31/08/2008 kl. 23:27
kilden bruker

stemmer
21

Et annet eksempel:

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

resulterer i

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

Merk at igroup er en iterator (en sub-iterator som dokumentasjon kaller det).

Dette er nyttig for klump- en 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)

Et annet eksempel på groupby - når tastene ikke er sortert. I følgende eksempel blir elementene i xx gruppert etter verdier i yy. I dette tilfellet, ett sett med nuller er produksjonen først, etterfulgt av et sett av de, etterfulgt igjen av et sett med nuller.

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

produserer:

0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]
Svarte 21/01/2013 kl. 16:54
kilden bruker

stemmer
18

ADVARSEL:

Syntaksen listen (groupby (...)) vil ikke fungere slik at du har tenkt. Det ser ut til å ødelegge de interne iteratorknapper objekter, så bruker

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

vil produsere:

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

I stedet for liste (groupby (...)), prøv [(k, liste (g)) for k, g i groupby (...)], eller hvis du bruker denne syntaksen ofte,

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

og få adgang til den groupby funksjonalitet og samtidig unngå de irriterende (for liten data) itera alle sammen.

Svarte 16/11/2013 kl. 00:39
kilden bruker

stemmer
15

itertools.groupby er et verktøy for å gruppere elementer.

Fra docs , sanke vi videre hva det kan gjøre:

# [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 gjenstander utbytte nøkkel-gruppeparene hvor gruppen er en generator.

Egenskaper

  • A. Gruppe etterfølgende elementer sammen
  • B. Gruppe alle forekomster av en vare, gitt en sortert iterable
  • C. Angi hvordan å gruppere elementer med en nøkkelfunksjon

sammenligninger

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

Bruker

Merk: Flere av de siste eksemplene stammer fra Víctor Terrón s PyCon (talk) (spansk) , "Kung Fu at Dawn med Itertools". Se også groupbykildekoden er skrevet i C.


Respons

# OP: Yes, you can use `groupby`, e.g. 
[do_something(list(g)) for _, g in groupby(lxml_elements, key=criteria_func)]
Svarte 25/08/2017 kl. 02:26
kilden bruker

stemmer
9

Jeg ønsker å gi et annet eksempel der groupby uten liksom ikke fungerer. Tilpasset fra eksempel ved 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 " "

produksjonen er

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.

det er to grupper med vehicule, mens man kunne forvente bare én gruppe

Svarte 07/05/2013 kl. 20:09
kilden bruker

stemmer
6

@CaptSolo, prøvde jeg ditt eksempel, men det fungerte ikke.

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

Produksjon:

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

Som du kan se, er det to o og to e-tallet, men de kom inn i separate grupper. Det var da jeg innså at du trenger å sortere listen sendes til groupby funksjonen. Så ville riktig bruk være:

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

Produksjon:

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

Bare å huske, hvis listen ikke er sortert, det groupby funksjonen vil ikke fungere !

Svarte 15/10/2009 kl. 15:41
kilden bruker

stemmer
5

Hvordan bruker jeg Pythons itertools.groupby ()?

Du kan bruke groupby å gruppere ting å iterere over. Du gir groupby en iterable, og en valgfri tast funksjon / callable med å kontrollere elementene som de kommer ut av iterable, og den gir en iterator som gir en to-tuppel av resultatet av nøkkelen callable og selve elementene i en annen iterable. Fra hjelp:

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

Her er et eksempel på groupby bruke en coroutine å gruppere etter en teller, bruker den en nøkkel Callable (i dette tilfellet coroutine.send) for å bare spytte ut tellingen for hvor mange gjentakelser og en gruppert under iterator elementer:

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

utskrifter

[(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
Svarte 27/07/2015 kl. 18:06
kilden bruker

stemmer
4

Sortering og 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'}
Svarte 01/08/2017 kl. 07:14
kilden bruker

stemmer
1

Du kan skrive egne groupby funksjon:

           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]}
Svarte 10/10/2018 kl. 17:53
kilden bruker

stemmer
1

Et nyttig eksempel på at jeg kom over kan være nyttig:

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)

Prøve inngang: 14445221

Eksempel utgang: (1,1) (3,4) (1,5) (2,2) (1,1)

Svarte 18/06/2017 kl. 17:16
kilden bruker

stemmer
-1

Gjør en iterator som returnerer påfølgende nøkler og grupper fra iterable. Nøkkelen er en funksjon beregning av en nøkkelverdi for hvert 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
Svarte 23/08/2018 kl. 06:44
kilden bruker

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