У мене є сценарій, коли користувач хоче застосувати кілька фільтрів до об'єкта Pandas DataFrame або Series. По суті, я хочу ефективно зв'язати купу фільтруючих (порівняльних операцій) разом, які задаються користувачем під час виконання.
Фільтри повинні бути добавками (але кожен застосований повинен звужувати результати).
Зараз я використовую, reindex()
але це створює новий об'єкт кожного разу і копіює базові дані (якщо я правильно розумію документацію). Отже, це може бути дійсно неефективним при фільтрації великої серії або DataFrame.
Я маю в виду , що використання apply()
, map()
або що - щось подібне може бути краще. Я досить новачок у Pandas, хоча так усе ще намагаюся обернути голову навколо всього.
TL; DR
Я хочу взяти словник наступної форми і застосувати кожну операцію до заданого об'єкта Series та повернути об’єкт серії «відфільтрований».
relops = {'>=': [1], '<=': [1]}
Довгий приклад
Почну з прикладу того, що я маю на даний момент, і просто фільтрую один об’єкт Series. Нижче наведена функція, яку я зараз використовую:
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
Користувач надає словник з операціями, які хоче виконати:
>>> 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
Знову ж таки, «проблема» мого вищезазначеного підходу полягає в тому, що, на мою думку, існує велика кількість непотрібних копій даних для кроків між проміжками.
Також я хотів би розширити це, щоб словник, який було передано, міг включати стовпці для оператора та фільтрувати цілий DataFrame на основі вхідного словника. Однак я припускаю, що всі роботи для цієї серії можуть бути легко розширені до DataFrame.
df.query
і pd.eval
здається, що добре підходить для вашого випадку використання. Для отримання інформації про pd.eval()
сімейство функцій, їх особливості та випадки використання, будь ласка, відвідайте Динамічну оцінку вираження в пандах за допомогою pd.eval () .