Jak wybrać wiersze w DataFrame między dwiema wartościami w Python Pandas?

102

Próbuję zmodyfikować DataFrame, dfaby zawierała tylko wiersze, dla których wartości w kolumnie closing_pricemieszczą się w przedziale od 99 do 101 i próbuję to zrobić za pomocą poniższego kodu.

Jednak pojawia się błąd

ValueError: Wartość prawdziwości serii jest niejednoznaczna. Użyj a.empty, a.bool (), a.item (), a.any () lub a.all ()

i zastanawiam się, czy można to zrobić bez używania pętli.

df = df[(99 <= df['closing_price'] <= 101)]
user131983
źródło
Kwestia jest taka, że nie można porównywać skalar z tablicą stąd błędzie, dla porównania trzeba użyć operatory bitowe i ująć je w nawiasach powodu pierwszeństwa operatora
EdChum
df.queryi pd.evalwydaje się, że dobrze pasuje do tego przypadku użycia. Aby uzyskać informacje na temat pd.eval()rodziny funkcji, ich funkcji i przypadków użycia, odwiedź stronę Dynamic Expression Evaluation w pandach przy użyciu pd.eval () .
cs95

Odpowiedzi:

108

Do ()grupowania wektora boolowskiego należy użyć, aby usunąć niejednoznaczność.

df = df[(df['closing_price'] >= 99) & (df['closing_price'] <= 101)]
Jianxun Li
źródło
177

Rozważ także serie między :

df = df[df['closing_price'].between(99, 101)]
Parfait
źródło
6
Opcja inclusive=Truejest używana domyślnie w programie between, więc możesz zapytać w ten sposóbdf = df[df['closing_price'].between(99, 101)]
Anton Ermakov,
3
to najlepsza odpowiedź! dobra robota!
PEBKAC
Czy w pandach istnieje funkcja „nie pomiędzy”? Nie znajduję tego.
dsugasa
3
@dsugasa, użyj operatora tyldy z between.
Parfait
1
@dsugasa np.df = df[~df['closing_price'].between(99, 101)]
stycznia
23

jest fajniejsza alternatywa - użyj metody 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

UPDATE: odpowiadając na komentarz:

Podoba mi się tutaj składnia, ale upadłem, gdy próbowałem połączyć z wyrażeniem; 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
MaxU
źródło
Podoba mi się tutaj składnia, ale spadła, gdy próbowałem połączyć z wyrażeniem; df.query ('(średnia + 2 * sd) <= cena_zamknięcia <= (średnia + 2 * sd)')
mapowanie dom
1
@mappingdom, co to jest meani sd? Czy to nazwy kolumn?
MaxU
nie są one obliczoną średnią i odchyleniem standardowym przechowywanym jako liczba zmiennoprzecinkowa
mapowanie dom
@mappingdom, co masz na myśli mówiąc „zapisane”?
MaxU
@mappingdom, zaktualizowałem swój post - czy o to prosiłeś?
MaxU
9

możesz również użyć .between()metody

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

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

Wynik

wprowadź opis obrazu tutaj

Riz.Khan
źródło
7
newdf = df.query('closing_price.mean() <= closing_price <= closing_price.std()')

lub

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

newdf = df.query('@mean <= closing_price <= @std')
crashMOGWAI
źródło
3

Jeśli masz do czynienia z wieloma wartościami i wieloma danymi wejściowymi, możesz również skonfigurować taką funkcję stosującą. W tym przypadku filtrowanie ramki danych pod kątem lokalizacji GPS mieszczących się w określonych zakresach.

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)]
wróbel
źródło
1

Zamiast tego

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

Powinieneś tego użyć

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

Musimy użyć bitowych operatorów logicznych NumPy |, &, ~, ^ do zapytań złożonych. Również nawiasy są ważne dla pierwszeństwa operatorów.

Aby uzyskać więcej informacji, możesz odwiedzić łącze: porównania, maski i logika boolowska

Rushabh Agarwal
źródło