Ich habe ein Szenario, in dem ein Benutzer mehrere Filter auf ein Pandas DataFrame- oder Serienobjekt anwenden möchte. Im Wesentlichen möchte ich eine Reihe von Filtern (Vergleichsoperationen) effizient miteinander verketten, die zur Laufzeit vom Benutzer angegeben werden.
Die Filter sollten additiv sein (auch bekannt als sollte jeder angewendete Filter die Ergebnisse einschränken).
Ich benutze gerade reindex()
aber dies erstellt jedes Mal ein neues Objekt und kopiert die zugrunde liegenden Daten (wenn ich die Dokumentation richtig verstehe). Dies kann also beim Filtern einer großen Serie oder eines DataFrames sehr ineffizient sein.
Ich denke das mit apply()
, map()
oder etwas Ähnliches könnte besser sein. Ich bin ziemlich neu bei Pandas, versuche aber immer noch, meinen Kopf um alles zu wickeln.
TL; DR
Ich möchte ein Wörterbuch der folgenden Form nehmen und jede Operation auf ein bestimmtes Serienobjekt anwenden und ein 'gefiltertes' Serienobjekt zurückgeben.
relops = {'>=': [1], '<=': [1]}
Langes Beispiel
Ich beginne mit einem Beispiel für das, was ich derzeit habe, und filtere nur ein einzelnes Serienobjekt. Unten ist die Funktion, die ich gerade benutze:
def apply_relops(series, relops):
"""
Pass dictionary of relational operators to perform on given series object
"""
for op, vals in relops.iteritems():
op_func = ops[op]
for val in vals:
filtered = op_func(series, val)
series = series.reindex(series[filtered])
return series
Der Benutzer stellt ein Wörterbuch mit den Operationen bereit, die er ausführen möchte:
>>> df = pandas.DataFrame({'col1': [0, 1, 2], 'col2': [10, 11, 12]})
>>> print df
>>> print df
col1 col2
0 0 10
1 1 11
2 2 12
>>> from operator import le, ge
>>> ops ={'>=': ge, '<=': le}
>>> apply_relops(df['col1'], {'>=': [1]})
col1
1 1
2 2
Name: col1
>>> apply_relops(df['col1'], relops = {'>=': [1], '<=': [1]})
col1
1 1
Name: col1
Wiederum besteht das "Problem" bei meinem obigen Ansatz darin, dass ich denke, dass es eine Menge möglicherweise unnötiger Kopien der Daten für die Zwischenschritte gibt.
Außerdem möchte ich dies erweitern, damit das übergebene Wörterbuch die zu operierenden Spalten enthalten und einen gesamten DataFrame basierend auf dem Eingabewörterbuch filtern kann. Ich gehe jedoch davon aus, dass alles, was für die Serie funktioniert, problemlos zu einem DataFrame erweitert werden kann.
df.query
und pd.eval
scheinen gut zu Ihrem Anwendungsfall zu passen. Informationen zur pd.eval()
Funktionsfamilie, ihren Funktionen und Anwendungsfällen finden Sie unter Auswertung dynamischer Ausdrücke in Pandas mit pd.eval () .