Wie verwende ich Pythons itertools.groupby ()?

  • Ich konnte keine verständliche Erklärung finden, wie Pythons Funktion itertools.groupby() tatsächlich verwendet wird. Was ich versuche, ist folgendes:

    • Nehmen Sie eine Liste - in diesem Fall die Kinder eines objektivierten lxml -Elements
    • Unterteilen Sie die Gruppe nach bestimmten Kriterien.
    • Später durchlaufen Sie jede dieser Gruppen separat.

    Ich habe die Dokumentation und die Beispiele , aber ich hatte Mühe, sie über eine einfache Liste von zu installieren Zahlen.

    Wie verwende ich itertools.groupby()? Gibt es eine andere Technik, die ich verwenden sollte? Hinweise auf ein gutes Lesen der "Voraussetzungen" wären ebenfalls willkommen.

    07 August 2014
    jmunsch
11 answers
  • Wie Sebastjan sagte, müssen Sie zunächst Ihre Daten sortieren. Das ist wichtig.

    Der Teil, den ich nicht bekommen habe, ist, dass in der Beispielkonstruktion

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

    k ist der aktuelle Gruppierungsschlüssel und g ist ein Iterator, mit dem Sie die durch diesen Gruppierungsschlüssel definierte Gruppe durchlaufen können. Mit anderen Worten, der Iterator groupby gibt Iteratoren selbst zurück.

    Hier ist ein Beispiel, das klarere Variablennamen verwendet:

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

    Damit erhalten Sie die Ausgabe:

    Ein Bär ist ein Tier.
    Eine Ente ist ein Tier.

    Ein Kaktus ist eine Pflanze.

    Ein Schnellboot ist ein Fahrzeug.
    Ein Schulbus ist ein Fahrzeug.

    In diesem Beispiel ist things eine Liste von Tupeln, in denen sich der erste Eintrag befindet In jedem Tupel befindet sich die Gruppe, zu der das zweite Element gehört.

    Die Funktion groupby() hat zwei Argumente: (1) die zu gruppierenden Daten und (2) die zu gruppierende Funktion.

    Hier weist lambda x: x[0] an, groupby() das erste Element in jedem Tupel als Gruppierungsschlüssel zu verwenden.

    In der Über der Anweisung for gibt groupby drei Paare (Schlüssel, Gruppeniterator) zurück - einmal für jeden eindeutigen Schlüssel. Sie können den zurückgegebenen Iterator verwenden, um jedes einzelne Element in dieser Gruppe zu durchlaufen.

    Hier ist ein etwas anderes Beispiel mit den gleichen Daten und verwendet ein Listenverständnis:

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

    Hier erhalten Sie die Ausgabe:

    Tiere : Bär und Ente.
    Pflanzen: Kaktus.
    Fahrzeuge: Schnellboot und Schulbus.

    04 December 2015
    Kevin GuanRuben
  • Können Sie uns Ihren Code zeigen?

    Das Beispiel in den Python-Dokumenten ist recht einfach:

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

    In Ihrem Fall handelt es sich bei Daten also um eine Liste von Knoten, bei keyfunc handelt es sich um die Logik Ihrer Kriterienfunktion und dann gruppiert groupby() die Daten

    Sie müssen die Daten nach den Kriterien sortieren, bevor Sie groupby aufrufen, da dies nicht funktioniert. Die Methode groupby durchläuft gerade eine Liste und bei jeder Änderung des Schlüssels wird eine neue Gruppe erstellt.

    04 December 2015
    Kevin GuanRuben
  • Ein neato-Trick mit groupby besteht darin, die Längencodierung in einer Zeile auszuführen:

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

    Geben Sie eine Liste von 2-Tupeln an, bei denen das erste Element das Zeichen und das 2. Element die Anzahl der Wiederholungen ist.

    Bearbeiten: Beachten Sie, dass itertools.groupby hiervon getrennt ist SQL GROUP BY -Semantik: itertools kann den Iterator nicht (und kann ihn im Allgemeinen nicht) vorab sortieren, sodass Gruppen mit demselben "Schlüssel" nicht zusammengeführt werden.

    08 August 2017
    nimish
  • Ein anderes Beispiel:

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

    führt zu

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

    Beachten Sie, dass igroup ein Iterator ist (ein Unter-Iterator, wie die Dokumentation es nennt).

    Dies ist nützlich, um einen Generator zu teilen:

     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)
     

    Ein weiteres Beispiel für groupby - wenn die Schlüssel nicht sortiert sind. Im folgenden Beispiel werden Elemente in xx nach Werten in yy gruppiert. In diesem Fall wird zuerst ein Satz von Nullen ausgegeben, gefolgt von einem Satz von Einsen, gefolgt von einem Satz von 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])
     

    Produziert:

     0 [0, 1, 2]
    1 [3, 4, 5]
    0 [6, 7, 8, 9]
     
    21 January 2013
    user650654
  • WARNUNG:

    Die Syntaxliste (groupby (...)) funktioniert nicht so, wie Sie es beabsichtigen. Es scheint, die internen Iteratorobjekte zu zerstören. Wenn Sie

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

    verwenden, wird Folgendes erzeugt:

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

    Statt von list (groupby (...)) versuchen Sie [(k, list (g)) für k, g in groupby (...)], oder wenn Sie diese Syntax häufig verwenden,

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

    und erhalten Sie Zugriff auf die Groupby-Funktionalität unter Vermeidung dieser lästigen (für kleine Daten) Iteratoren alle zusammen

    28 December 2014
    The Red PeaDJPeter
  • itertools.groupby ist ein Tool zum Gruppieren von Elementen.

    Von die Dokumente , wir zeigen Ihnen, was es tun könnte:

    # [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 -Objekte liefern Schlüsselgruppenpaare, in denen sich die Gruppe befindet einen Generator.

    Funktionen

    • A. Gruppieren Sie aufeinander folgende Elemente
    • B. Gruppieren Sie alle Vorkommen eines Elements bei einer sortierten iterierbaren
    • C. Legen Sie fest, wie Elemente mit einer Schlüsselfunktion gruppiert werden sollen.

    Vergleiche

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

    Verwendungen

    Hinweis: Mehrere der letzteren Beispiele stammen von PyCon von Víctor Terrón (talk) (spanisch) ," Dawn with Itertools ". Siehe auch das Kapitel groupby Code in C geschrieben.


    Antwort

    && 7&&] e> <
    20 August 2018
    pylang
  • Ich möchte ein anderes Beispiel geben, bei dem Gruppierung ohne Sortierung nicht funktioniert. Aus dem Beispiel von 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 " "
     

    ist die Ausgabe

     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.
     

    Es gibt zwei Gruppen mit Vehicule, während man nur eine Gruppe erwarten kann

    19 October 2013
    nutshipoctoback
  • @CaptSolo, ich habe Ihr Beispiel ausprobiert, aber es hat nicht funktioniert.

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

    Ausgabe:

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

    Wie Sie sehen können, gibt es zwei O's und zwei E's, die sich jedoch in getrennten Gruppen befinden . Da wurde mir klar, dass Sie die an die Groupby-Funktion übergebene Liste sortieren müssen. Die korrekte Verwendung wäre also:

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

    Ausgabe:

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

    Wenn die Liste nicht sortiert wird, funktioniert die Gruppierungsfunktion nicht ! !

    12 November 2015
    Craig S. AndersonOscarGarcia
  • Wie verwende ich Pythons itertools.groupby ()?

    Sie können groupby verwenden, um Dinge zu gruppieren, die wiederholt werden sollen. Sie geben groupby eine iterierbare und eine optionale key -Funktion / aufrufbare Funktion, mit der Sie die Elemente überprüfen können, wenn sie aus der iterierbaren Funktion kommen. Außerdem wird ein Iterator zurückgegeben, der das Ergebnis des Ergebnisses mit einem Doppel-Tupel zurückgibt Schlüssel aufrufbar und die tatsächlichen Elemente in einer anderen iterierbaren. Aus der Hilfe:

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

    Hier ein Beispiel, wie groupby eine Coroutine verwendet, um nach einem Zähler zu gruppieren Taste aufrufbar (in diesem Fall coroutine.send), um nur die Anzahl der Iterationen und einen gruppierten Unter-Iterator von Elementen auszuspucken:

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

    Drucke

     [(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9])]
     
    27 July 2015
    Aaron HallTarkaDaal
  • Sortieren und Gruppieren nach

     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'}
     
    20 August 2018
    Aashish GahlawatSatyajit Das