Come selezionare le righe in un DataFrame tra due valori, in Python Pandas?


99

Sto cercando di modificare un DataFrame dfper contenere solo righe per i quali i valori nella colonna closing_pricesono compresi tra 99 e 101 e sto provando a farlo con il codice seguente.

Tuttavia, ottengo l'errore

ValueError: il valore di verità di una serie è ambiguo. Usa a.empty, a.bool (), a.item (), a.any () o a.all ()

e mi chiedo se esiste un modo per farlo senza utilizzare i loop.

df = df[(99 <= df['closing_price'] <= 101)]

Il problema qui è che non puoi confrontare uno scalare con un array, quindi l'errore, per i confronti devi usare gli operatori bit per bit e racchiuderli tra parentesi a causa della precedenza degli operatori
EdChum

df.querye pd.evalsembrano buoni per questo caso d'uso. Per informazioni sulla pd.eval()famiglia di funzioni, le loro caratteristiche e i casi d'uso, visita la pagina Valutazione delle espressioni dinamiche nei panda utilizzando pd.eval () .
cs95

Risposte:


103

Dovresti usare ()per raggruppare il tuo vettore booleano per rimuovere l'ambiguità.

df = df[(df['closing_price'] >= 99) & (df['closing_price'] <= 101)]

163

Considera anche le serie tra :

df = df[df['closing_price'].between(99, 101)]

5
L'opzione inclusive=Trueè utilizzata per impostazione predefinita in between, quindi puoi eseguire una query in questo mododf = df[df['closing_price'].between(99, 101)]
Anton Ermakov

3
questa è la risposta migliore! ottimo lavoro!
PEBKAC

C'è una funzionalità "non tra" nei panda? Non lo trovo.
dsugasa

3
@dsugasa, usa l' operatore tilde con between.
Parfait

1
@dsugasa egdf = df[~df['closing_price'].between(99, 101)]
Jan33

22

c'è un'alternativa migliore: usa il metodo query () :

In [58]: df = pd.DataFrame({'closing_price': np.random.randint(95, 105, 10)})

In [59]: df
Out[59]:
   closing_price
0            104
1             99
2             98
3             95
4            103
5            101
6            101
7             99
8             95
9             96

In [60]: df.query('99 <= closing_price <= 101')
Out[60]:
   closing_price
1             99
5            101
6            101
7             99

AGGIORNAMENTO: rispondendo al commento:

Mi piace la sintassi qui, ma è caduto quando si cerca di combinare con expresison; df.query('(mean + 2 *sd) <= closing_price <=(mean + 2 *sd)')

In [161]: qry = "(closing_price.mean() - 2*closing_price.std())" +\
     ...:       " <= closing_price <= " + \
     ...:       "(closing_price.mean() + 2*closing_price.std())"
     ...:

In [162]: df.query(qry)
Out[162]:
   closing_price
0             97
1            101
2             97
3             95
4            100
5             99
6            100
7            101
8             99
9             95

Mi piace la sintassi qui, ma è caduto quando si cerca di combinare con expresison; df.query ('(mean + 2 * sd) <= closing_price <= (mean + 2 * sd)')
mapping dom

1
@mappingdom, cos'è meane sd? Quei nomi di colonne?
MaxU

no, sono la media calcolata e la deviazione standard memorizzata come un valore a virgola mobile
mappatura dom

@mappingdom, cosa intendi dire "archiviato"?
MaxU

@mappingdom, ho aggiornato il mio post - è quello che stavi chiedendo?
MaxU

9

puoi anche usare il .between()metodo

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")

emp[emp["Salary"].between(60000, 61000)]

Produzione

inserisci qui la descrizione dell'immagine


6
newdf = df.query('closing_price.mean() <= closing_price <= closing_price.std()')

o

mean = closing_price.mean()
std = closing_price.std()

newdf = df.query('@mean <= closing_price <= @std')

3

Se hai a che fare con più valori e più input, potresti anche impostare una funzione di applicazione come questa. In questo caso filtrare un dataframe per posizioni GPS che rientrano in determinati intervalli.

def filter_values(lat,lon):
    if abs(lat - 33.77) < .01 and abs(lon - -118.16) < .01:
        return True
    elif abs(lat - 37.79) < .01 and abs(lon - -122.39) < .01:
        return True
    else:
        return False


df = df[df.apply(lambda x: filter_values(x['lat'],x['lon']),axis=1)]

1

Invece di questo

df = df[(99 <= df['closing_price'] <= 101)]

Dovresti usare questo

df = df[(df['closing_price']>=99 ) & (df['closing_price']<=101)]

Dobbiamo usare gli operatori logici bit per bit di NumPy |, &, ~, ^ per le query composte. Inoltre, le parentesi sono importanti per la precedenza degli operatori.

Per ulteriori informazioni, puoi visitare il collegamento: Confronti, maschere e logica booleana

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.