Tengo un escenario en el que un usuario quiere aplicar varios filtros a un objeto Pandas DataFrame o Series. Esencialmente, quiero encadenar eficientemente un conjunto de filtros (operaciones de comparación) que el usuario especifica en tiempo de ejecución.
Los filtros deben ser aditivos (es decir, cada uno aplicado debe reducir los resultados).
Actualmente estoy usando, reindex()
pero esto crea un nuevo objeto cada vez y copia los datos subyacentes (si entiendo la documentación correctamente). Por lo tanto, esto podría ser realmente ineficiente al filtrar una gran serie o un marco de datos.
Estoy pensando que el uso de apply()
, map()
o algo similar podría ser mejor. Sin embargo, soy bastante nuevo en Pandas, así que todavía estoy tratando de entender todo.
TL; DR
Quiero tomar un diccionario de la siguiente forma y aplicar cada operación a un objeto Serie dado y devolver un objeto Serie 'filtrado'.
relops = {'>=': [1], '<=': [1]}
Ejemplo largo
Comenzaré con un ejemplo de lo que tengo actualmente y simplemente filtrando un solo objeto de la Serie. A continuación se muestra la función que estoy usando actualmente:
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
El usuario proporciona un diccionario con las operaciones que desea realizar:
>>> 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
Nuevamente, el 'problema' con mi enfoque anterior es que creo que hay muchas copias posiblemente innecesarias de los datos para los pasos intermedios.
Además, me gustaría expandir esto para que el diccionario aprobado pueda incluir las columnas para operar y filtrar un DataFrame completo basado en el diccionario de entrada. Sin embargo, supongo que todo lo que funcione para la Serie se puede expandir fácilmente a un Marco de datos.
df.query
y pd.eval
parece que encaja bien con su caso de uso. Para obtener información sobre la pd.eval()
familia de funciones, sus características y casos de uso, visite Evaluación de expresión dinámica en pandas usando pd.eval () .