2017-10-19 2 views
0

Ich versuche, Pandas zu verwenden pd.DataFrame.where wie folgt:Alternative effizienten Ansatz für Pandas wo

df.where(cond=mask, other=df.applymap(f)) 

Wo f eine benutzerdefinierte Funktion ist auf einer einzelnen Zelle zu betreiben. Ich kann other=f nicht verwenden, da es scheint, ein anderes Ergebnis zu produzieren.

Also im Grunde möchte ich die Funktion f an allen Zellen des DataFrame, die eine Bedingung nicht erfüllt, die ich als mask angegeben bin.

Die obige Verwendung mit where nicht sehr effizient ist, wie es f sofort für den gesamten Datenrahmen wertet df, während ich es nur bei einigen Einträgen der Datenrahmen bewerten müssen, die manchmal nur sehr wenige spezifische Einträge im Vergleich zu den gesamten sein kann Datenrahmen.

Gibt es eine alternative Verwendung/Vorgehensweise, die diesen allgemeinen Fall effizienter lösen könnte?

+2

Können Sie Beispieldaten und Funktionsdefinitionen angeben? – skrubber

+0

Können Sie nicht ändern, f? Wenn nicht, "df.applymap (Lambda x: f (x) wenn cond else x)" sollte es tun, ohne wo. – ayhan

Antwort

1

Wie Sie richtig angegeben haben, wird df.applymap(f) vor df.where() ausgewertet. Ich bin ziemlich sicher, dass df.where() eine schnelle Funktion ist und hier nicht der Flaschenhals ist.

Es ist wahrscheinlicher, dass df.applymap(f) ineffizient ist, und es gibt normalerweise eine schnellere Möglichkeit, f vektorisiert zu machen. Nachdem Sie dies gesagt haben und f selbst langsam ist, können Sie f ändern, um die Eingabe unverändert zu lassen, wo immer Ihre Maske False ist. Dies wird jedoch wahrscheinlich sehr langsam sein und Sie werden definitiv lieber versuchen, f zu vektorisieren.

Wenn Sie wirklich tun müssen, es elementweise, könnten Sie eine NumPy Array verwenden:

result = df.values 
for (i,j) in np.where(mask): 
    result[i,j] = f(result[i,j]) 

Es ist wichtig, dass Sie eine NumPy Array für diese verwenden, anstatt .iloc oder .loc im Datenrahmen, weil die Indizierung Ein Pandas-Datenrahmen ist langsam.

Sie könnten die Geschwindigkeit mit .applymap vergleichen; für die gleiche Operation, glaube ich nicht .applymap ist wesentlich schneller (wenn überhaupt) als einfach eine for-Schleife, denn alle Pandas macht eine eigene for-Schleife in Python (vielleicht Cython? Aber auch das spart nur die Overhead, und nicht die Funktion selbst). Dies unterscheidet sich von der "richtigen" Vektorisierung, da Vektoroperationen in C implementiert sind.

+0

'Sie könnten f ändern, um die Eingabe unverändert zu lassen, wo immer Ihre Maske False ist 'ist genau das, wonach ich suche. Wie würdest du das erreichen? – user113531

+0

Ich habe diese Aussage tatsächlich unter der Annahme gemacht, dass Ihre boolesche Maske nur von den Werten Ihrer Daten abhängt, was wahrscheinlich nicht der Fall ist. Wenn es das nicht ist, dann ist es unmöglich, auf eine lächerliche Verwendung globaler Variablen zu verzichten. Dies liegt daran, dass '.applymap' nur den Wert (und nicht den Index) in' f' übergibt. –

Verwandte Themen