Effizientere Methode zum Säubern einer Stringsspalte und Hinzufügen einer neuen Spalte

8

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 :

%Vor%

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.

%Vor%

Wenn ich es benutze, bekomme ich das:

%Vor%

Gibt es einen besseren (gelesen, "schneller") Weg, um dieselbe Aufgabe zu erledigen?

    
user3002486 21.12.2016, 18:34
quelle

3 Antworten

11

Es ist viel besser, wenn Sie Ihren Index mit metric_type und unstacking setzen.

%Vor%

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

%Vor%
  

1 Schleife, beste von 3: 57,4 s pro Schleife

    
piRSquared 21.12.2016, 18:41
quelle
2

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).

    
JohnE 31.12.2016 16:50
quelle
2

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:

  1. 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.

  2. 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.

  3. Sortiere diese erhaltenen Spalten, so dass sie lexikographisch sortiert sind und die duplizierten (falls vorhanden) nebeneinander platziert werden. Lassen Sie die DF gemäß dieser Kombination von Spalten geändert werden.
  4. Verwenden Sie den Parameter np.unique mit return_index=True , um die vorhandenen eindeutigen Spalten und die entsprechenden Indizes zu extrahieren.
  5. Wir müssen einen Weg finden, um die identischen Spalten in eine einzige Spalte zu gruppieren. Dafür können wir 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 ).
  6. Die zurückgegebene 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.
  7. Unser 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:

%Vor%     
Nickil Maveli 02.01.2017 21:08
quelle

Tags und Links