Wie man eine Python-Liste effizient basierend auf einer gegebenen Funktion gruppiert

PythonPythonBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Das Organisieren und Manipulieren von Datensammlungen ist eine grundlegende Aufgabe in der Python-Programmierung. Eine häufige Operation ist das Gruppieren von Listenelementen basierend auf bestimmten Kriterien. Dieser Prozess transformiert Ihre Daten in organisierte Kategorien, wodurch es einfacher wird, sie zu analysieren und mit ihnen zu arbeiten.

In diesem Tutorial erfahren Sie, wie Sie Elemente in einer Python-Liste effizient mit verschiedenen Techniken gruppieren können. Wir beginnen mit grundlegenden Ansätzen und führen nach und nach leistungsfähigere integrierte Funktionen für diesen Zweck ein. Am Ende dieses Labs werden Sie ein praktisches Verständnis für verschiedene Möglichkeiten haben, Listendaten in Python zu gruppieren.

Grundlegendes Listengruppieren mit Dictionaries

Beginnen wir damit, zu verstehen, was Listengruppierung bedeutet und wie man eine grundlegende Gruppierungstechnik mit Python-Dictionaries implementiert.

Was ist Listengruppierung?

Listengruppierung ist der Prozess des Organisierens von Listenelementen in Kategorien basierend auf einem bestimmten Merkmal oder einer Funktion. Beispielsweise möchten Sie möglicherweise eine Liste von Zahlen danach gruppieren, ob sie gerade oder ungerade sind, oder eine Liste von Wörtern nach ihrem Anfangsbuchstaben gruppieren.

Verwenden von Dictionaries für die grundlegende Gruppierung

Der einfachste Weg, Listenelemente in Python zu gruppieren, ist die Verwendung eines Dictionaries:

  • Die Schlüssel (keys) repräsentieren die Gruppen
  • Die Werte (values) sind Listen, die die Elemente enthalten, die zu jeder Gruppe gehören

Erstellen wir ein einfaches Beispiel, in dem wir Zahlen danach gruppieren, ob sie gerade oder ungerade sind.

Schritt 1: Erstellen einer Python-Datei

Erstellen wir zunächst eine neue Python-Datei, um unseren Code zu schreiben:

  1. Öffnen Sie die WebIDE und erstellen Sie eine neue Datei namens group_numbers.py im Verzeichnis /home/labex/project.

  2. Fügen Sie der Datei den folgenden Code hinzu:

## Basic list grouping using dictionaries
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

## Initialize empty dictionary to store our groups
even_odd_groups = {"even": [], "odd": []}

## Group numbers based on whether they are even or odd
for num in numbers:
    if num % 2 == 0:
        even_odd_groups["even"].append(num)
    else:
        even_odd_groups["odd"].append(num)

## Print the resulting groups
print("Grouping numbers by even/odd:")
print(f"Even numbers: {even_odd_groups['even']}")
print(f"Odd numbers: {even_odd_groups['odd']}")
  1. Speichern Sie die Datei.

Schritt 2: Ausführen des Python-Skripts

Führen Sie das Skript aus, um die Ergebnisse zu sehen:

  1. Öffnen Sie ein Terminal in der WebIDE.

  2. Führen Sie das Skript aus:

python3 /home/labex/project/group_numbers.py

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

Grouping numbers by even/odd:
Even numbers: [2, 4, 6, 8, 10]
Odd numbers: [1, 3, 5, 7, 9]

Schritt 3: Gruppieren nach einem komplexeren Kriterium

Ändern wir nun unser Skript, um Zahlen basierend auf ihrem Rest bei der Division durch 3 zu gruppieren:

  1. Fügen Sie Ihrer Datei group_numbers.py den folgenden Code hinzu:
## Group numbers by remainder when divided by 3
remainder_groups = {0: [], 1: [], 2: []}

for num in numbers:
    remainder = num % 3
    remainder_groups[remainder].append(num)

print("\nGrouping numbers by remainder when divided by 3:")
for remainder, nums in remainder_groups.items():
    print(f"Numbers with remainder {remainder}: {nums}")
  1. Speichern Sie die Datei.

  2. Führen Sie das Skript erneut aus:

python3 /home/labex/project/group_numbers.py

Nun sollten Sie eine zusätzliche Ausgabe sehen:

Grouping numbers by remainder when divided by 3:
Numbers with remainder 0: [3, 6, 9]
Numbers with remainder 1: [1, 4, 7, 10]
Numbers with remainder 2: [2, 5, 8]

Diese grundlegende Technik mit Dictionaries bietet eine unkomplizierte Möglichkeit, Listenelemente zu gruppieren. Wenn Ihre Gruppierungsanforderungen jedoch komplexer werden, bietet Python leistungsfähigere und effizientere Methoden, die wir in den nächsten Schritten untersuchen werden.

Verwenden von itertools.groupby() für effizientes Gruppieren

Nachdem Sie das Grundkonzept des Gruppierens verstanden haben, wollen wir einen leistungsfähigeren Ansatz mit der integrierten Funktion itertools.groupby() untersuchen. Diese Funktion ist besonders nützlich, wenn man mit sortierten Daten arbeitet.

Verständnis von itertools.groupby()

Die Funktion groupby() aus dem Modul itertools gruppiert aufeinanderfolgende Elemente in einem Iterable basierend auf einer Schlüssel-Funktion. Sie gibt einen Iterator zurück, der Paare erzeugt aus:

  • Dem Wert, der von der Schlüssel-Funktion zurückgegeben wird
  • Einem Iterator, der die Elemente in der Gruppe erzeugt

Wichtiger Hinweis: groupby() gruppiert nur aufeinanderfolgende Elemente, daher müssen die Eingabedaten typischerweise zuerst sortiert werden.

Lassen Sie uns ein Beispiel implementieren, um zu sehen, wie dies in der Praxis funktioniert.

Schritt 1: Erstellen einer neuen Python-Datei

  1. Erstellen Sie eine neue Datei namens groupby_example.py im Verzeichnis /home/labex/project.

  2. Fügen Sie den folgenden Code hinzu, um das notwendige Modul zu importieren:

import itertools

## Sample data
words = ["apple", "banana", "avocado", "blueberry", "apricot", "blackberry"]

Schritt 2: Wörter nach dem ersten Buchstaben gruppieren

Verwenden wir nun itertools.groupby(), um die Wörter nach ihrem ersten Buchstaben zu gruppieren:

  1. Fügen Sie den folgenden Code zu Ihrer Datei groupby_example.py hinzu:
## First, we need to sort the list by the key we'll use for grouping
## In this case, the first letter of each word
words.sort(key=lambda x: x[0])
print("Sorted words:", words)

## Now group by first letter
grouped_words = {}
for first_letter, group in itertools.groupby(words, key=lambda x: x[0]):
    grouped_words[first_letter] = list(group)

## Print the resulting groups
print("\nGrouping words by first letter:")
for letter, words_group in grouped_words.items():
    print(f"Words starting with '{letter}': {words_group}")
  1. Speichern Sie die Datei.

  2. Führen Sie das Skript aus:

python3 /home/labex/project/groupby_example.py

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

Sorted words: ['apple', 'apricot', 'avocado', 'banana', 'blackberry', 'blueberry']

Grouping words by first letter:
Words starting with 'a': ['apple', 'apricot', 'avocado']
Words starting with 'b': ['banana', 'blackberry', 'blueberry']

Schritt 3: Die Bedeutung des Sortierens verstehen

Um zu demonstrieren, warum das Sortieren bei der Verwendung von groupby() entscheidend ist, fügen wir ein weiteres Beispiel ohne Sortierung hinzu:

  1. Fügen Sie den folgenden Code zu Ihrer Datei groupby_example.py hinzu:
## Sample data (unsorted)
unsorted_words = ["apple", "banana", "avocado", "blueberry", "apricot", "blackberry"]

print("\n--- Without sorting first ---")
print("Original words:", unsorted_words)

## Try to group without sorting
unsorted_grouped = {}
for first_letter, group in itertools.groupby(unsorted_words, key=lambda x: x[0]):
    unsorted_grouped[first_letter] = list(group)

print("\nGrouping without sorting:")
for letter, words_group in unsorted_grouped.items():
    print(f"Words starting with '{letter}': {words_group}")
  1. Speichern Sie die Datei.

  2. Führen Sie das Skript erneut aus:

python3 /home/labex/project/groupby_example.py

In der Ausgabe werden Sie feststellen, dass die Gruppierung ohne Sortierung unterschiedliche Ergebnisse liefert:

--- Without sorting first ---
Original words: ['apple', 'banana', 'avocado', 'blueberry', 'apricot', 'blackberry']

Grouping without sorting:
Words starting with 'a': ['apple']
Words starting with 'b': ['banana']
Words starting with 'a': ['avocado']
Words starting with 'b': ['blueberry']
Words starting with 'a': ['apricot']
Words starting with 'b': ['blackberry']

Beachten Sie, wie wir mehrere Gruppen mit demselben Schlüssel haben. Dies geschieht, weil groupby() nur aufeinanderfolgende Elemente gruppiert. Wenn die Daten nicht sortiert sind, werden Elemente mit demselben Schlüssel, die an verschiedenen Positionen in der Liste erscheinen, in separate Gruppen eingeordnet.

Die Funktion itertools.groupby() ist sehr effizient und Teil der Standardbibliothek, was sie zu einem leistungsstarken Werkzeug für viele Gruppierungsaufgaben macht. Denken Sie jedoch daran, dass sie am besten mit sortierten Daten funktioniert.

Gruppieren mit collections.defaultdict

Ein weiteres leistungsstarkes Werkzeug für das Gruppieren in Python ist die Klasse defaultdict aus dem Modul collections. Dieser Ansatz bietet eine sauberere, effizientere Möglichkeit, Daten zu gruppieren, verglichen mit der Verwendung regulärer Dictionaries.

Verständnis von defaultdict

Ein defaultdict ist eine Dictionary-Unterklasse, die den ersten Wert für einen fehlenden Schlüssel automatisch initialisiert. Dies eliminiert die Notwendigkeit zu überprüfen, ob ein Schlüssel existiert, bevor ein Element zu einem Dictionary hinzugefügt wird. Für Gruppierungszwecke bedeutet dies, dass wir vermeiden können, bedingten Code zu schreiben, um leere Listen für neue Gruppen zu initialisieren.

Sehen wir uns an, wie defaultdict den Gruppierungsprozess vereinfacht.

Schritt 1: Erstellen einer neuen Python-Datei

  1. Erstellen Sie eine neue Datei namens defaultdict_grouping.py im Verzeichnis /home/labex/project.

  2. Fügen Sie den folgenden Code hinzu, um das notwendige Modul zu importieren und einige Beispieldaten zu erstellen:

from collections import defaultdict

## Sample data - a list of people with their ages
people = [
    {"name": "Alice", "age": 25, "city": "New York"},
    {"name": "Bob", "age": 30, "city": "Boston"},
    {"name": "Charlie", "age": 35, "city": "Chicago"},
    {"name": "David", "age": 25, "city": "Denver"},
    {"name": "Eve", "age": 30, "city": "Boston"},
    {"name": "Frank", "age": 35, "city": "Chicago"},
    {"name": "Grace", "age": 25, "city": "New York"}
]

Schritt 2: Personen nach Alter gruppieren

Verwenden wir nun defaultdict, um Personen nach ihrem Alter zu gruppieren:

  1. Fügen Sie den folgenden Code zu Ihrer Datei defaultdict_grouping.py hinzu:
## Group people by age using defaultdict
age_groups = defaultdict(list)

for person in people:
    age_groups[person["age"]].append(person["name"])

## Print the resulting groups
print("Grouping people by age:")
for age, names in age_groups.items():
    print(f"Age {age}: {names}")
  1. Speichern Sie die Datei.

  2. Führen Sie das Skript aus:

python3 /home/labex/project/defaultdict_grouping.py

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

Grouping people by age:
Age 25: ['Alice', 'David', 'Grace']
Age 30: ['Bob', 'Eve']
Age 35: ['Charlie', 'Frank']

Schritt 3: Vergleich mit dem regulären Dictionary-Ansatz

Um den Vorteil der Verwendung von defaultdict zu verstehen, vergleichen wir ihn mit dem regulären Dictionary-Ansatz:

  1. Fügen Sie den folgenden Code zu Ihrer Datei defaultdict_grouping.py hinzu:
print("\n--- Comparison with regular dictionary ---")

## Using a regular dictionary (the conventional way)
regular_dict_groups = {}

for person in people:
    age = person["age"]
    name = person["name"]

    ## Need to check if the key exists
    if age not in regular_dict_groups:
        regular_dict_groups[age] = []

    regular_dict_groups[age].append(name)

print("\nRegular dictionary approach:")
for age, names in regular_dict_groups.items():
    print(f"Age {age}: {names}")
  1. Speichern Sie die Datei.

  2. Führen Sie das Skript erneut aus:

python3 /home/labex/project/defaultdict_grouping.py

Sie werden feststellen, dass beide Ansätze das gleiche Ergebnis liefern, aber der defaultdict-Ansatz sauberer ist und weniger Code erfordert.

Schritt 4: Gruppieren nach mehreren Kriterien

Erweitern wir nun unser Beispiel, um Personen sowohl nach Stadt als auch nach Alter zu gruppieren:

  1. Fügen Sie den folgenden Code zu Ihrer Datei defaultdict_grouping.py hinzu:
## Grouping by city and then by age
city_age_groups = defaultdict(lambda: defaultdict(list))

for person in people:
    city = person["city"]
    age = person["age"]
    name = person["name"]

    city_age_groups[city][age].append(name)

print("\nGrouping people by city and then by age:")
for city, age_groups in city_age_groups.items():
    print(f"\nCity: {city}")
    for age, names in age_groups.items():
        print(f"  Age {age}: {names}")
  1. Speichern Sie die Datei.

  2. Führen Sie das Skript erneut aus:

python3 /home/labex/project/defaultdict_grouping.py

Sie sollten eine zusätzliche Ausgabe ähnlich der folgenden sehen:

Grouping people by city and then by age:

City: New York
  Age 25: ['Alice', 'Grace']

City: Boston
  Age 30: ['Bob', 'Eve']

City: Chicago
  Age 35: ['Charlie', 'Frank']

City: Denver
  Age 25: ['David']

Dieser verschachtelte defaultdict-Ansatz ermöglicht komplexere Gruppierungshierarchien mit minimalem Code. Der defaultdict ist besonders nützlich, wenn Sie nicht alle Gruppenschlüssel im Voraus kennen, da er bei Bedarf automatisch neue Gruppen erstellt.

Praktische Anwendung: Datenanalyse mit Gruppierungstechniken

Nachdem Sie verschiedene Methoden zur Gruppierung von Daten verstanden haben, wollen wir diese Techniken anwenden, um ein reales Problem zu lösen: die Analyse eines Datensatzes von Schülerdatensätzen. Wir werden verschiedene Gruppierungsmethoden verwenden, um nützliche Informationen aus den Daten zu extrahieren.

Einrichten des Beispieldatensatzes

Zuerst erstellen wir unseren Schülerdatensatz:

  1. Erstellen Sie eine neue Datei namens student_analysis.py im Verzeichnis /home/labex/project.

  2. Fügen Sie den folgenden Code hinzu, um die Beispieldaten einzurichten:

import itertools
from collections import defaultdict

## Sample student data
students = [
    {"id": 1, "name": "Emma", "grade": "A", "subject": "Math", "score": 95},
    {"id": 2, "name": "Noah", "grade": "B", "subject": "Math", "score": 82},
    {"id": 3, "name": "Olivia", "grade": "A", "subject": "Science", "score": 90},
    {"id": 4, "name": "Liam", "grade": "C", "subject": "Math", "score": 75},
    {"id": 5, "name": "Ava", "grade": "B", "subject": "Science", "score": 88},
    {"id": 6, "name": "William", "grade": "A", "subject": "History", "score": 96},
    {"id": 7, "name": "Sophia", "grade": "B", "subject": "History", "score": 85},
    {"id": 8, "name": "James", "grade": "C", "subject": "Science", "score": 72},
    {"id": 9, "name": "Isabella", "grade": "A", "subject": "Math", "score": 91},
    {"id": 10, "name": "Benjamin", "grade": "B", "subject": "History", "score": 84}
]

print("Student Records:")
for student in students:
    print(f"ID: {student['id']}, Name: {student['name']}, Subject: {student['subject']}, Grade: {student['grade']}, Score: {student['score']}")
  1. Speichern Sie die Datei.

Verwenden von defaultdict, um Schüler nach Fach zu gruppieren

Analysieren wir, welche Schüler jedes Fach belegen:

  1. Fügen Sie den folgenden Code zu Ihrer Datei student_analysis.py hinzu:
print("\n--- Students Grouped by Subject ---")

## Group students by subject using defaultdict
subject_groups = defaultdict(list)

for student in students:
    subject_groups[student["subject"]].append(student["name"])

## Print students by subject
for subject, names in subject_groups.items():
    print(f"{subject}: {names}")
  1. Speichern Sie die Datei.

Berechnen der Durchschnittsnoten nach Fach

Berechnen wir die Durchschnittsnote für jedes Fach:

  1. Fügen Sie den folgenden Code zu Ihrer Datei student_analysis.py hinzu:
print("\n--- Average Scores by Subject ---")

## Calculate average scores for each subject
subject_scores = defaultdict(list)

for student in students:
    subject_scores[student["subject"]].append(student["score"])

## Calculate and print averages
for subject, scores in subject_scores.items():
    average = sum(scores) / len(scores)
    print(f"{subject} Average: {average:.2f}")
  1. Speichern Sie die Datei.

Verwenden von itertools.groupby() zur Analyse der Noten

Verwenden wir nun itertools.groupby(), um die Verteilung der Noten zu analysieren:

  1. Fügen Sie den folgenden Code zu Ihrer Datei student_analysis.py hinzu:
print("\n--- Grade Distribution (using itertools.groupby) ---")

## Sort students by grade first
sorted_students = sorted(students, key=lambda x: x["grade"])

## Group and count students by grade
grade_counts = {}
for grade, group in itertools.groupby(sorted_students, key=lambda x: x["grade"]):
    grade_counts[grade] = len(list(group))

## Print grade distribution
for grade, count in grade_counts.items():
    print(f"Grade {grade}: {count} students")
  1. Speichern Sie die Datei.

Kombinieren von Techniken: Erweiterte Analyse

Schließlich wollen wir eine komplexere Analyse durchführen, indem wir unsere Gruppierungstechniken kombinieren:

  1. Fügen Sie den folgenden Code zu Ihrer Datei student_analysis.py hinzu:
print("\n--- Advanced Analysis: Grade Distribution by Subject ---")

## Group by subject and grade
subject_grade_counts = defaultdict(lambda: defaultdict(int))

for student in students:
    subject = student["subject"]
    grade = student["grade"]
    subject_grade_counts[subject][grade] += 1

## Print detailed grade distribution by subject
for subject, grades in subject_grade_counts.items():
    print(f"\n{subject}:")
    for grade, count in grades.items():
        print(f"  Grade {grade}: {count} students")
  1. Speichern Sie die Datei.

  2. Führen Sie das vollständige Skript aus:

python3 /home/labex/project/student_analysis.py

Sie sollten eine umfassende Analyse der Schülerdaten sehen, einschließlich:

  • Schülerdatensätze
  • Schüler nach Fach gruppiert
  • Durchschnittsnoten nach Fach
  • Gesamtnotenverteilung
  • Notenverteilung nach Fach

Dieses Beispiel zeigt, wie verschiedene Gruppierungstechniken kombiniert werden können, um komplexe Datenanalysen mit relativ einfachem Code durchzuführen. Jeder Ansatz hat seine Stärken:

  • defaultdict eignet sich hervorragend für einfaches Gruppieren, ohne die Existenz von Schlüsseln überprüfen zu müssen
  • itertools.groupby() ist effizient für die Arbeit mit sortierten Daten
  • Die Kombination von Techniken ermöglicht mehrstufiges Gruppieren und komplexe Analysen

Die Auswahl der richtigen Gruppierungstechnik hängt von Ihren spezifischen Anforderungen und der Struktur Ihrer Daten ab.

Zusammenfassung

In diesem Tutorial haben Sie mehrere effiziente Methoden zum Gruppieren von Listen in Python gelernt:

  1. Grundlegendes Dictionary-Gruppieren: Sie begannen mit einem grundlegenden Ansatz unter Verwendung regulärer Dictionaries, um Gruppen basierend auf bestimmten Kriterien zu erstellen.

  2. itertools.groupby(): Sie haben diese eingebaute Funktion erkundet, die aufeinanderfolgende Elemente in sortierten Daten effizient gruppiert, und ihre Vorteile und Einschränkungen verstanden.

  3. collections.defaultdict: Sie haben diese praktische Dictionary-Unterklasse verwendet, die fehlende Schlüssel automatisch behandelt und Ihren Gruppierungscode sauberer und prägnanter macht.

  4. Praktische Datenanalyse: Sie haben diese Techniken angewendet, um einen Datensatz zu analysieren, und gesehen, wie sie einzeln und in Kombination verwendet werden können, um aussagekräftige Erkenntnisse zu gewinnen.

Jede dieser Methoden hat ihre Stärken und idealen Anwendungsfälle:

  • Verwenden Sie grundlegende Dictionaries für einfaches Gruppieren, wenn Klarheit wichtiger ist als Prägnanz.
  • Verwenden Sie itertools.groupby(), wenn Ihre Daten sortiert sind oder nach dem Gruppierungsschlüssel sortiert werden können.
  • Verwenden Sie defaultdict, wenn Sie sauberen, prägnanten Code wünschen und nicht alle Gruppenschlüssel im Voraus kennen.
  • Kombinieren Sie Techniken für komplexe, mehrstufige Gruppierungen und Analysen.

Durch die Beherrschung dieser Gruppierungstechniken haben Sie Ihrem Python-Programmier-Toolkit leistungsstarke Werkzeuge hinzugefügt, die Ihnen helfen, Daten effizienter zu organisieren, zu analysieren und zu manipulieren.