Ich habe einen Pandas DataFrame , df_test
. Es enthält eine Spalte 'Größe', die die Größe in Bytes darstellt. Ich habe KB, MB und GB mit dem folgenden Code berechnet:
df_test = pd.DataFrame([
{'dir': '/Users/uname1', 'size': 994933},
{'dir': '/Users/uname2', 'size': 109338711},
])
df_test['size_kb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0, grouping=True) + ' KB')
df_test['size_mb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0 ** 2, grouping=True) + ' MB')
df_test['size_gb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0 ** 3, grouping=True) + ' GB')
df_test
dir size size_kb size_mb size_gb
0 /Users/uname1 994933 971.6 KB 0.9 MB 0.0 GB
1 /Users/uname2 109338711 106,776.1 KB 104.3 MB 0.1 GB
[2 rows x 5 columns]
Ich habe dies über 120.000 Zeilen ausgeführt und es dauert ungefähr 2,97 Sekunden pro Spalte * 3 = ~ 9 Sekunden gemäß% timeit.
Kann ich das trotzdem schneller machen? Kann ich beispielsweise, anstatt jeweils eine Spalte nach dem Anwenden zurückzugeben und dreimal auszuführen, alle drei Spalten in einem Durchgang zurückgeben, um sie wieder in den ursprünglichen Datenrahmen einzufügen?
Die anderen Fragen, die ich gefunden habe, möchten alle mehrere Werte annehmen und einen einzelnen Wert zurückgeben . Ich möchte einen einzelnen Wert annehmen und mehrere Spalten zurückgeben .
rows_list
in dieser Antwort?pd.Series(data, index=...)
. Andernfalls erhalten Sie kryptische Fehler, wenn Sie versuchen, das Ergebnis wieder dem übergeordneten Datenrahmen zuzuweisen.Verwenden Sie anwenden und Reißverschluss wird 3-mal schneller als Serie Weg.
Testergebnisse sind:
quelle
Einige der aktuellen Antworten funktionieren einwandfrei, aber ich möchte eine andere, möglicherweise "pandifiziertere" Option anbieten. Dies funktioniert bei mir mit den aktuellen Pandas 0.23 (nicht sicher, ob es in früheren Versionen funktioniert):
Beachten Sie, dass der Trick auf dem
result_type
Parameter von liegtapply
, der das Ergebnis in einen erweitertDataFrame
, der direkt neuen / alten Spalten zugewiesen werden kann.quelle
Nur ein weiterer lesbarer Weg. Dieser Code fügt drei neue Spalten und deren Werte hinzu und gibt Reihen ohne Verwendung von Parametern in der Apply-Funktion zurück.
Ein allgemeines Beispiel aus: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.apply.html
quelle
Wirklich coole Antworten! Danke Jesse und Jaumebonet! Nur einige Bemerkungen zu:
zip(* ...
... result_type="expand")
Obwohl expand etwas eleganter ( pandifiziert ) ist, ist der Reißverschluss mindestens ** 2x schneller . In diesem einfachen Beispiel unten bin ich 4x schneller geworden .
quelle
Die Leistung zwischen den Top-Antworten ist sehr unterschiedlich, und Jesse & famaral42 haben dies bereits diskutiert, aber es lohnt sich, einen fairen Vergleich zwischen den Top-Antworten zu teilen und auf ein subtiles, aber wichtiges Detail von Jesses Antwort einzugehen: das Argument, das an die Funktion, wirkt sich auch auf die Leistung aus .
(Python 3.7.4, Pandas 1.0.3)
Hier sind die Ergebnisse:
Beachten Sie, wie Tupel Rückkehr ist die schnellste Methode, aber was passiert ist in als Argument, wirkt sich auch auf die Leistung. Der Unterschied im Code ist geringfügig, aber die Leistungsverbesserung ist erheblich.
Test Nr. 4 (Bestehen eines einzelnen Werts) ist doppelt so schnell wie Test Nr. 3 (Bestehen einer Reihe), obwohl die durchgeführte Operation angeblich identisch ist.
Aber es gibt noch mehr ...
In einigen Fällen (Nr. 1a und Nr. 4a) ist das Anwenden der Funktion auf einen DataFrame, in dem die Ausgabespalten bereits vorhanden sind, schneller als das Erstellen aus der Funktion.
Hier ist der Code zum Ausführen der Tests:
quelle
Ich glaube, dass die Version 1.1 das in der oberen Antwort hier vorgeschlagene Verhalten verletzt.
Der obige Code lief auf Pandas 1.1.0 und gibt Folgendes zurück:
In Pandas 1.0.5 kehrte es zurück:
Was ich denke, ist das, was Sie erwarten würden.
Sie sind sich nicht sicher, wie die Versionshinweise dieses Verhalten erklären. Wie hier erläutert, wird jedoch das alte Verhalten wiederbelebt, indem eine Mutation der ursprünglichen Zeilen durch Kopieren vermieden wird. dh:
quelle
Um mehrere Werte zurückzugeben, gehe ich im Allgemeinen folgendermaßen vor
Das endgültige Zurückgeben eines Datenrahmens hat seine Vorteile, ist jedoch manchmal nicht erforderlich. Sie können sich die
apply()
Ergebnisse ansehen und ein wenig mit den Funktionen spielen;)quelle
Es gibt einen neuen Datenrahmen mit zwei Spalten aus der ursprünglichen.
quelle