Mam scenariusz, w którym użytkownik chce zastosować kilka filtrów do obiektu Pandas DataFrame lub Series. Zasadniczo chcę wydajnie łączyć kilka operacji filtrowania (operacji porównania), które są określane w czasie wykonywania przez użytkownika.
Filtry powinny być addytywne (każdy zastosowany powinien zawęzić wyniki).
Obecnie używam, reindex()ale za każdym razem tworzy to nowy obiekt i kopiuje podstawowe dane (jeśli dobrze rozumiem dokumentację). Tak więc może to być naprawdę nieefektywne podczas filtrowania dużej serii lub ramki DataFrame.
Myślę, że za pomocą apply(), map()lub coś podobnego mogłoby być lepiej. Jestem całkiem nowy w Pandach, więc wciąż próbuję wszystko ogarnąć.
TL; DR
Chcę wziąć słownik w poniższej formie i zastosować każdą operację do danego obiektu Series i zwrócić „przefiltrowany” obiekt Series.
relops = {'>=': [1], '<=': [1]}
Długi przykład
Zacznę od przykładu tego, co mam obecnie i tylko filtrując pojedynczy obiekt Series. Poniżej znajduje się funkcja, której obecnie używam:
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
Użytkownik udostępnia słownik z operacjami, które chce wykonać:
>>> 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
Ponownie, „problem” z moim powyższym podejściem polega na tym, że wydaje mi się, że jest dużo prawdopodobnie niepotrzebnego kopiowania danych w krokach pośrednich.
Chciałbym również rozszerzyć to, aby przekazywany słownik mógł zawierać kolumny do operatora i filtrować całą ramkę DataFrame na podstawie słownika wejściowego. Zakładam jednak, że wszystko, co działa w serii, można łatwo rozszerzyć do ramki DataFrame.
df.queryi pd.evalwydaje się, że dobrze pasuje do twojego przypadku użycia. Aby uzyskać informacje na temat pd.eval()rodziny funkcji, ich funkcji i przypadków użycia, odwiedź stronę Ocena wyrażeń dynamicznych w pandach przy użyciu pd.eval () .