Eu tenho um cenário em que um usuário deseja aplicar vários filtros a um objeto Pandas DataFrame ou Series. Essencialmente, quero encadear com eficiência um conjunto de filtros (operações de comparação) que são especificados em tempo de execução pelo usuário.
Os filtros devem ser aditivos (ou seja, cada um aplicado deve restringir os resultados).
Atualmente, estou usando, reindex()
mas isso cria um novo objeto a cada vez e copia os dados subjacentes (se eu entender a documentação corretamente). Portanto, isso pode ser realmente ineficiente ao filtrar uma grande série ou DataFrame.
Estou pensando que o uso apply()
, map()
ou algo semelhante poderia ser melhor. Eu sou muito novo no Pandas, embora ainda esteja tentando entender tudo.
TL; DR
Eu quero pegar um dicionário do seguinte formulário e aplicar cada operação a um determinado objeto Series e retornar um objeto Series 'filtrado'.
relops = {'>=': [1], '<=': [1]}
Exemplo longo
Começarei com um exemplo do que tenho atualmente e apenas filtrarei um único objeto Series. Abaixo está a função que estou usando atualmente:
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
O usuário fornece um dicionário com as operações que deseja executar:
>>> 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
Novamente, o "problema" da minha abordagem acima é que acho que há muitas cópias possivelmente desnecessárias dos dados para as etapas intermediárias.
Além disso, eu gostaria de expandir isso para que o dicionário transmitido possa incluir as colunas para o operador e filtrar um DataFrame inteiro com base no dicionário de entrada. No entanto, estou assumindo que tudo o que funciona para a série pode ser facilmente expandido para um DataFrame.
df.query
e pd.eval
parece ser um bom ajuste para o seu caso de uso. Para obter informações sobre a pd.eval()
família de funções, seus recursos e casos de uso, visite Avaliação de Expressão Dinâmica em pandas usando pd.eval () .