Beim Erlernen von Knowledge Science im Jahr 2020 warfare Pandas eines der beliebtesten Instruments. Obwohl sich neue Instruments darauf konzentrieren, die Schwächen von Pandas bei der Verarbeitung sehr großer Datenmengen zu verbessern, verwende ich Pandas immer noch für viele Datenbereinigungs-, Verarbeitungs- und Analyseaufgaben. Ja, Pandas macht es mir schwer, mit Milliarden von Zeilen zu arbeiten, aber für die Arbeit mit allem, was darunter liegt, ist es definitiv mehr als genug.
Ich sehe Pandas nicht nur für EDA oder in Notebooks, sondern auch in Produktionssystemen.
In diesem Artikel werde ich einige Datenbereinigungs- und -verarbeitungsvorgänge durchgehen, um zu zeigen, wie leistungsfähig Pandas ist.
Beginnen wir mit dem Datensatz, der Inventory Protecting Models (SKUs) und Such-API-Antworten für diese SKUs enthält.
import pandas as pd
search_results = pd.read_csv("search_results.csv")
search_results.head()

Das Suchergebnis ist eine Liste von Wörterbüchern und sieht folgendermaßen aus:
search_results.loc(0, "search_result")
"({'my_id': 'HBCV00007F5Y2B', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00007UPQBM', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00008I29IH', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00006U3ZYB', 'distance': 0.8961254358291626, 'entity': {}},
{'my_id': 'HBCV0000AFA4H6', 'distance': 0.8702399730682373, 'entity': {}},
{'my_id': 'HBCV00009CDGD4', 'distance': 0.86175537109375, 'entity': {}},
{'my_id': 'HBCV000046336T', 'distance': 0.8594968318939209, 'entity': {}},
{'my_id': 'HBCV00009QDZRT', 'distance': 0.8572311997413635, 'entity': {}},
{'my_id': 'HBCV00008E11P3', 'distance': 0.8553324937820435, 'entity': {}},
{'my_id': 'HBV00000C4IY6', 'distance': 0.8539167642593384, 'entity': {}})
... and 5 entities remaining"
Wie wir in der Ausgabe sehen, handelt es sich aufgrund des letzten Teils („… und 5 verbleibende Entitäten“) nicht um eine richtige Liste des Wörterbuchformats. Außerdem wird es als einzelne Zeichenfolge gespeichert.
Um es besser nutzen zu können, müssen wir es in eine richtige Liste von Wörterbüchern konvertieren. Die folgende Codezeile entfernt den letzten Teil, indem sie die Zeichenfolge bei „…“ teilt und die erste Teilung übernimmt.
search_results.loc(0, "search_result").break up("...")(0).strip()
Die Ausgabe ist jedoch immer noch eine einzelne Zeichenfolge. Wir können das integrierte ast-Modul von Python verwenden, um es in eine Liste umzuwandeln:
import ast
res = ast.literal_eval(search_results.loc(0, "search_result").break up("...")(0).strip())
res
({'my_id': 'HBCV00007F5Y2B', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00007UPQBM', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00008I29IH', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00006U3ZYB', 'distance': 0.8961254358291626, 'entity': {}},
{'my_id': 'HBCV0000AFA4H6', 'distance': 0.8702399730682373, 'entity': {}},
{'my_id': 'HBCV00009CDGD4', 'distance': 0.86175537109375, 'entity': {}},
{'my_id': 'HBCV000046336T', 'distance': 0.8594968318939209, 'entity': {}},
{'my_id': 'HBCV00009QDZRT', 'distance': 0.8572311997413635, 'entity': {}},
{'my_id': 'HBCV00008E11P3', 'distance': 0.8553324937820435, 'entity': {}},
{'my_id': 'HBV00000C4IY6', 'distance': 0.8539167642593384, 'entity': {}})
Wir haben jetzt die Suchergebnisse als richtige Liste von Wörterbüchern. Dies galt nur für eine einzelne Reihe. Wir müssen den gleichen Vorgang auf alle SKUs (dh die gesamte SKU-Spalte) anwenden.
Eine Möglichkeit besteht darin, alle Zeilen in einer for-Schleife durchzugehen und denselben Vorgang auszuführen. Dies ist jedoch nicht die beste Possibility. Wir sollten vektorisierte Operationen bevorzugen, wenn wir können. Eine vektorisierte Operation bedeutet im Wesentlichen, dass der Code in allen Zeilen gleichzeitig ausgeführt wird.
Bei einer einzelnen Zeile habe ich die Aufteilung verwendet, um den letzten Teil der Zeichenfolge zu entfernen, aber bei einer vektorisierten Operation funktionierte das nicht. Eine robustere Possibility scheint die Verwendung eines regulären Ausdrucks zu sein.
search_results.loc(:, 'search_result') = search_results('search_result').str.substitute(r"....*", "", regex=True).str.strip()
Dieser Code wählt „…“ und alles, was danach kommt, aus und ersetzt sie durch nichts. Mit anderen Worten: Der Teil „… und 5 verbleibende Entitäten“ wird entfernt.
Wir haben jetzt alle Zeilen in der Suchergebnisspalte als richtige Liste von Wörterbüchern.
search_results.loc(10, "search_result")
"({'my_id': 'HBCV00007F5Y2B', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00007UPQBM', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00008I29IH', 'distance': 1.0, 'entity': {}},
{'my_id': 'HBCV00006U3ZYB', 'distance': 0.8961254358291626, 'entity': {}},
{'my_id': 'HBCV0000AFA4H6', 'distance': 0.8702399730682373, 'entity': {}},
{'my_id': 'HBCV00009CDGD4', 'distance': 0.86175537109375, 'entity': {}},
{'my_id': 'HBCV000046336T', 'distance': 0.8594968318939209, 'entity': {}},
{'my_id': 'HBCV00009QDZRT', 'distance': 0.8572311997413635, 'entity': {}},
{'my_id': 'HBCV00008E11P3', 'distance': 0.8553324937820435, 'entity': {}},
{'my_id': 'HBV00000C4IY6', 'distance': 0.8539167642593384, 'entity': {}})"
Sie werden immer noch als String gespeichert, aber ich kann sie mit dem ast-Modul problemlos in eine Liste konvertieren, was ich im nächsten Schritt tun werde.
Was mich interessiert, sind die SKUs, die in den Suchergebnissen zurückgegeben werden. Ich erstelle eine neue Spalte, indem ich die SKUs in den Wörterbüchern extrahiere. Ich kann über den „my_id“-Schlüssel des Wörterbuchs darauf zugreifen.
Es gibt 3 Teile dieser Operation:
- Konvertieren Sie die Suchergebniszeichenfolge mithilfe der Funktion literal_eval in eine Liste
- Extrahieren Sie die SKU aus dem my_id-Schlüssel des Wörterbuchs
- Führen Sie dies in einem Listenverständnis durch, um SKUs aus allen Wörterbüchern in der Liste abzurufen
Wir können alle diese Operationen ausführen, indem wir wie folgt eine Lambda-Funktion auf alle Zeilen anwenden:
search_results.loc(:, "result_skus") =
search_results("search_result").apply(lambda x: (merchandise('my_id') for merchandise in ast.literal_eval(x)))
search_results.head()

Jede Zeile in der Spalte result_skus enthält eine Liste mit 10 SKUs. Nehmen wir an, ich muss diese 10 SKUs in verschiedenen Reihen haben. Für jede Zeile in der SKU-Spalte werden 10 Zeilen aus der Liste in der Spalte result_skus erstellt. In Pandas gibt es eine sehr einfache Möglichkeit, dies zu tun, nämlich die Explosionsfunktion.
knowledge = search_results(("sku", "result_skus")).explode("result_skus", ignore_index=True)
knowledge.head()

Wir haben einen neuen Datenrahmen mit der Spalte „sku“ und „result_skus“ erstellt. Die folgende Zeichnung zeigt, was die Explosionsfunktion bewirkt:

Betrachten Sie das Gegenteil. Wir haben einen Datenrahmen wie oben gezeigt, möchten aber alle Ergebnisse für eine SKU in einer einzigen Zeile haben.
Wir können die Funktion „groupby“ verwenden, um die Zeilen nach SKU zu gruppieren und dann die Funktion „Liste“ auf die Spalte „result_skus“ anwenden:
new_data = knowledge.groupby("sku", as_index=False)("result_skus").apply(record)
new_data.head()
Damit kehren wir zum vorherigen Schritt zurück:

Mit der Explosionsfunktion haben wir einen Datenrahmen mit einer separaten Zeile für jede SKU in der Spalte result_skus erstellt. Was ist, wenn wir sie in verschiedene Spalten statt in Zeilen aufteilen müssen?
Eine Möglichkeit besteht darin, die Funktion pd.Sequence auf die Spalte result_skus anzuwenden und die resultierenden Spalten mit dem ursprünglichen Datenrahmen zu verketten.
new_cols = new_data("result_skus").apply(pd.Sequence)
new_data = pd.concat((new_data, new_cols), axis=1)
new_data.head()

Die Spalten von 0 bis 9 enthalten die 10 SKUs in der Spalte result_skus. Dieser Code, der die Apply-Funktion verwendet, ist keine vektorisierte Operation.
Wir haben eine andere Possibility, die vektorisiert und viel schneller ist.
new_cols = pd.DataFrame(new_data("result_skus").tolist())
new_data = pd.concat((new_data, new_cols), axis=1)
Dieser Code liefert uns den gleichen Datenrahmen wie oben, jedoch viel schneller.
Ich habe eine typische Datenbereinigungs- und -verarbeitungsaufgabe demonstriert, mit der ein Datenwissenschaftler oder -analyst in seinem Job konfrontiert sein kann. Ich bin seit über 5 Jahren auf diesem Gebiet tätig und Pandas hat immer ausgereicht, um das zu tun, was ich brauche, außer bei der Arbeit mit sehr großen Datensätzen (z. B. Milliarden von Zeilen).
Die Instruments, die für solch große Datenmengen besser geeignet sind, haben eine ähnliche Syntax wie Pandas. PySpark ist beispielsweise eine Artwork Mischung aus Pandas und SQL. Von der Syntax her ist Polars Pandas sehr ähnlich. Daher ist das Erlernen und Üben von Pandas immer noch eine äußerst wertvolle Fähigkeit für jeden, der im Bereich Datenwissenschaft und KI arbeitet.
Vielen Dank fürs Lesen.
