Ich habe einen Datenrahmen df
mit den Spalten ['metric_type', 'metric_value']
. Für jede Zeile möchte ich sicherstellen, dass ich eine Spalte mit dem Namen 'metric_type'
und einem Wert für diese Spalte gleich 'metric_value'
habe.
Eines meiner Probleme ist, dass 'metric_type'
falsche Leerzeichen hat, die ich loswerden möchte.
Betrachte den Datenrahmen df
:
Beachten Sie, dass jeder Wert von 'metric_type'
Leerzeichen an verschiedenen Stellen enthält.
Ich habe eine Funktion erstellt, die apply
verwendet, aber es dauert schrecklich lange.
Wenn ich es benutze, bekomme ich das:
%Vor%Gibt es einen besseren (gelesen, "schneller") Weg, um dieselbe Aufgabe zu erledigen?
Es ist viel besser, wenn Sie Ihren Index mit metric_type
und unstacking setzen.
Demonstration
%Vor%oder mein Weg
%Vor%Timing
Verwenden Sie eine größere df
df1 = pd.concat([df] * 30000, ignore_index=True)
%Vor%10 Schleifen, best of 3: 77,3 ms pro Schleife
1 Schleife, beste von 3: 57,4 s pro Schleife
Hier ist eine Alternative, die etwa 20% schneller ist und die gleiche Antwort wie @ piRSquared gibt. Ich würde nicht vorschlagen, dass es entweder besser oder schlechter ist (im Allgemeinen), aber das Kopfgeld wurde gepostet, nachdem diese Antwort akzeptiert wurde, also werde ich dies als zusätzliche Option anbieten.
%Vor% Etwa 1/3 der Geschwindigkeitsverbesserung ergibt sich aus der Verwendung von strip
anstelle von replace
und 2/3 der Verwendung von pivot
anstelle von unstack
. (Der Schritt concat
ist sowieso gleich und extrem schnell).
Wenn man sich die Art und Weise ansieht, in der der endgültige Datenrahmen erstellt wird, scheint die One-Hot-Encoding-Funktion der String-Spalte im Vergleich zu den anderen bisher genannten Ansätzen keine schlechte Idee zu sein.
Schritte:
Erstellen Sie mit pd.get_dummies
in metric_type
series Dummy-Variablen aus kategorischen. Dieser Teil, der mit str.strip
gekoppelt ist, ist der zeitaufwendigste des Loses.
Anstatt vorangestellte / nachfolgende Whitespace-Zeichen direkt auf dem Serienobjekt zu entfernen, könnten wir mit der Berechnung des get_dummies
-Teils abschließen, da es hohe Chancen gibt, dass einige der kategorialen Variablen in der Serie später wiederholt werden würden während der Dummy-Erstellung dieselbe Spalte teilen. Je mehr duplizierte Variablen sind, desto geringer ist die Zeit, die für die Filterung dieser zusätzlichen Leerzeichen aufgewendet wird. Führen Sie str.strip
nur für die erhaltenen Spalten der Dummy-Variablen DF
aus. Dieser Ansatz ist eine große Zeitersparnis.
DF
gemäß dieser Kombination von Spalten geändert werden. np.unique
mit return_index=True
, um die vorhandenen eindeutigen Spalten und die entsprechenden Indizes zu extrahieren. np.add.reduceat
verwenden, was ähnlich funktioniert wie eine groupby
Operation (äquivalent - df.groupby(df.columns.tolist(), axis=1).sum()
), aber es hat seine Besonderheit darin, sehr schnell zu sein. Die zu paarenden Indizes werden von idx
von np.unique
geliefert. Die Reduzierung der Werte erfolgt in diesen Segmenten und ihre laufende Summe wird über Spalten hinweg berechnet ( axis=1
). dtype
ist bool
, was uns bei der Verwendung von np.where
hilft, da sie wie eine boolesche Maske funktioniert, wobei 1/0 auf True
/ False
abgebildet werden. Diese Einsen werden dann durch Werte in metric_value
series und 0's by NaN
gefüllt. DF
ist jetzt bereit, das mit dem ursprünglichen startenden DF
spaltenweise verkettet werden muss, was zum letzten bereinigten Datenrahmen führt. Lösung:
%Vor%Timings:
%Vor% Für ein DF
, das einige tausend Zeilen enthält, vergleichbar mit dem, was OP vorhatte: