Ho uno scenario in cui un utente vuole applicare diversi filtri a un oggetto Pandas DataFrame o Series. In sostanza, voglio unire in modo efficiente un insieme di filtri (operazioni di confronto) che sono specificati in fase di esecuzione dall'utente.
I filtri dovrebbero essere additivi (ovvero ognuno applicato dovrebbe restringere i risultati).
Attualmente sto usando reindex()
ma questo crea ogni volta un nuovo oggetto e copia i dati sottostanti (se capisco correttamente la documentazione). Quindi, questo potrebbe essere davvero inefficiente quando si filtra una grande serie o DataFrame.
Sto pensando che l'uso apply()
, map()
o qualcosa di simile potrebbe essere migliore. Sono abbastanza nuovo per i panda, anche se sto ancora cercando di avvolgere la mia testa intorno a tutto.
TL; DR
Voglio prendere un dizionario del seguente modulo e applicare ogni operazione a un determinato oggetto Serie e restituire un oggetto Serie "filtrato".
relops = {'>=': [1], '<=': [1]}
Esempio lungo
Inizierò con un esempio di ciò che ho attualmente e solo filtrando un singolo oggetto Serie. Di seguito è la funzione che sto attualmente utilizzando:
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
L'utente fornisce a un dizionario le operazioni che desidera eseguire:
>>> 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
Ancora una volta, il "problema" con il mio approccio di cui sopra è che penso che ci sia molta copia forse inutile dei dati per i passaggi intermedi.
Inoltre, vorrei espanderlo in modo che il dizionario passato possa includere le colonne su cui operare e filtrare un intero DataFrame in base al dizionario di input. Tuttavia, suppongo che qualunque cosa funzioni per la serie possa essere facilmente estesa a un DataFrame.
df.query
e pd.eval
sembrano adatti per il tuo caso d'uso. Per informazioni sulla pd.eval()
famiglia di funzioni, le loro caratteristiche e i casi d'uso, visitare la valutazione delle espressioni dinamiche in Panda usando pd.eval () .