Skip to content

GROUP BY in Python (itertools.groupby)

Python

In Python können Sie auf nebeneinander liegende Elemente mit demselben Wert in einem iterierbaren Objekt wie einer Liste mit itertools.groupby() gruppieren.

import itertools

l = [0, 0, 0, 1, 1, 2, 0, 0]
print([(k, list(g)) for k, g in itertools.groupby(l)])
# [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

Dieser Artikel hat folgenden Inhalt.

  • Verwendung von itertools.groupby()
  • Geben Sie eine Funktion an, die einen Schlüsselwert für jedes Element berechnet:key
  • Aggregat wie GROUP BY in SQL
  • Für Tupel und Streicher

Verwenden Sie collections.Counter, um die Anzahl der Elemente mit demselben Wert zu umfassen, unabhängig von ihrer Reihenfolge, dh auf fortlaufend oder nicht auf fortlaufend.

itertools.groupby() gibt einen Iterator von Schlüsseln und Gruppen zurück. Werte werden nicht von print() gedruckt.

l = [0, 0, 0, 1, 1, 2, 0, 0]
print(itertools.groupby(l))
# 

Die zurückerstattete Gruppe ist auch ein Iterator. Verwenden Sie beispielsweise list(), um eine Liste zu erstellen.

Die zurückerstattete Gruppe ist selbst ein Iterator, der die zugrunde liegende Iterable mit groupby() teilt. Da die Quelle gemeinsam genutzt WIRD, ist die vorherige Gruppe nicht mehr sichtbar, wenn das groupby()-Objekt erweitert WIRD. Wenn diese Daten später benötigt werden, sollten sie als Liste gespeichert werden:
itertools.groupby() – Funktionen, die Iteratoren für effiziente Schleifen erstellen – Python 3.10.4-Dokumentation

for k, g in itertools.groupby(l):
    print(k, g)
# 0 
# 1 
# 2 
# 0 

for k, g in itertools.groupby(l):
    print(k, list(g))
# 0 [0, 0, 0]
# 1 [1, 1]
# 2 [2]
# 0 [0, 0]

SIE can sterben Listenverständnisse verwenden, um nur eine Liste von Schlüsseln, nur Gruppen oder beides (Tupel aus Schlüssel und Gruppe) zu erhalten.

print([k for k, g in itertools.groupby(l)])
# [0, 1, 2, 0]

print([list(g) for k, g in itertools.groupby(l)])
# [[0, 0, 0], [1, 1], [2], [0, 0]]

print([(k, list(g)) for k, g in itertools.groupby(l)])
# [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

Geben Sie eine Funktion an, die einen Schlüsselwert für jedes Element berechnet:key

Sie können den Schlüsselparameter für itertools.groupby() angeben. Die Verwendung von key ist die gleiche wie bei anderen Funktionen wie sorted(), max(), min() usw.

Chronisch auf dem Ergebnis der in der Tonart angegebenen Funktion (aufrufbares Objekt) wird bestimmt, ob die Werte auf fortlaufender Elemente gleich sind.

Wenn SIE beispielsweise die eingebaute Funktion len() angeben, sterben die Länge (Anzahl der Zeichen) Einer Zeichenfolge zurückgibt, Werden Elemente mit derselben Länge gruppiert. Klammern () sind bei der Angabe des Schlüssels nicht erforderlich.

l = ['aaa', 'bbb', 'ccc', 'a', 'b', 'aa', 'bb']
print([(k, list(g)) for k, g in itertools.groupby(l, len)])
# [(3, ['aaa', 'bbb', 'ccc']), (1, ['a', 'b']), (2, ['aa', 'bb'])]

Stimmen Sie mit einem Lambda-Ausdruck ab, ob die Zahl gerade oder ungerade ist:

l = [0, 2, 0, 3, 1, 4, 4, 0]
print([(k, list(g)) for k, g in itertools.groupby(l, lambda x: x % 2)])
# [(0, [0, 2, 0]), (1, [3, 1]), (0, [4, 4, 0])]

Aggregat wie GROUP BY in SQL

Sie können zweidimensionale Daten (z. B. eine Liste von Listen) basierend auf einer bestimmten Spalte, wie GROUP BY in SQL, mit Schlüssel gruppieren.

Hier WIRD ein Lambda-Ausdruck used, um das Element an die gewünschte Position in der Liste zu bringen, aber auch operator.itemgetter() can used Werden.

Außerdem WIRD die for-Anweisung used, um die Ausgabe lesbarer zu machen, aber SIE can natürlich auch Listenverständnisse wie in den vorherigen Beispielen verwenden.

l = [[0, 'Alice', 0],
     [1, 'Alice', 10],
     [2, 'Bob', 20],
     [3, 'Bob', 30],
     [4, 'Alice', 40]]

for k, g in itertools.groupby(l, lambda x: x[1]):
    print(k, list(g))
# Alice [[0, 'Alice', 0], [1, 'Alice', 10]]
# Bob [[2, 'Bob', 20], [3, 'Bob', 30]]
# Alice [[4, 'Alice', 40]]

Mit itertools.groupby() werden nur aufeinanderfolgende Elemente mit demselben Wert gruppiert. Um sie unabhängig von der Reihenfolge zu gruppieren, sortieren Sie die ursprüngliche Liste mit sorted().

Beim Sortieren einer Liste von Listen wird die Liste standardmäßig nach dem ersten Element jeder Liste sortiert. Um nach dem Element an der angegebenen Position zu sortieren, geben Sie den Schlüsselparameter von sorted() an.

for k, g in itertools.groupby(sorted(l, key=lambda x: x[1]), lambda x: x[1]):
    print(k, list(g))
# Alice [[0, 'Alice', 0], [1, 'Alice', 10], [4, 'Alice', 40]]
# Bob [[2, 'Bob', 20], [3, 'Bob', 30]]

Summieren Sie die Zahlen mit einem Generatorausdruck:

for k, g in itertools.groupby(sorted(l, key=lambda x: x[1]), lambda x: x[1]):
    print(k, sum(x[2] for x in g))
# Alice 50
# Bob 50

Beachten Sie, dass Pandas auch groupby() für Gruppierung und Aggregation hat. Pandas ist bequemer für den Umgang mit komplexen Daten.

Für Tupel und Streicher

Sie können itertools.groupby() verwenden, um nicht nur Listen, sondern auch Tupel, Strings usw. zu verarbeiten.

Für Tupel:

t = (0, 0, 0, 1, 1, 2, 0, 0)
print([(k, list(g)) for k, g in itertools.groupby(t)])
# [(0, [0, 0, 0]), (1, [1, 1]), (2, [2]), (0, [0, 0])]

Verwenden Sie tuple(), wenn Sie aus einer Gruppe ein Tupel anstelle einer Liste machen möchten.

print(tuple((k, tuple(g)) for k, g in itertools.groupby(t)))
# ((0, (0, 0, 0)), (1, (1, 1)), (2, (2,)), (0, (0, 0)))

Für Saiten:

s = 'aaabbcaa'
print([(k, list(g)) for k, g in itertools.groupby(s)])
# [('a', ['a', 'a', 'a']), ('b', ['b', 'b']), ('c', ['c']), ('a', ['a', 'a'])]

Verwenden Sie join(), wenn Sie eine Gruppe in einen String umwandeln möchten.

print([(k, ''.join(g)) for k, g in itertools.groupby(s)])
# [('a', 'aaa'), ('b', 'bb'), ('c', 'c'), ('a', 'aa')]

Natürlich können Sie auch jedes andere iterierbare Objekt mit itertools.groupby() behandeln.