Pracuję z indeksem boolowskim w Pandach. Pytanie brzmi, dlaczego stwierdzenie:
a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]
działa dobrze, podczas gdy
a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]
kończy pracę z błędem?
Przykład:
a=pd.DataFrame({'x':[1,1],'y':[10,20]})
In: a[(a['x']==1)&(a['y']==10)]
Out: x y
0 1 10
In: a[(a['x']==1) and (a['y']==10)]
Out: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
and != &
.and
Operator Pythonie nie może być pominięte, natomiast&
operator (__and__
) puszki. Stąd wybór zastosowania&
u numpy i pand.Odpowiedzi:
Kiedy powiesz
Niejawnie prosisz Pythona o konwersję
(a['x']==1)
i(a['y']==10)
na wartości logiczne.Tablice NumPy (o długości większej niż 1) i obiekty Pandy, takie jak Series, nie mają wartości logicznej - innymi słowy, podnoszą
kiedy jest używany jako wartość logiczna. Dzieje się tak, ponieważ nie jest jasne, kiedy powinno być Prawdą czy fałszem . Niektórzy użytkownicy mogą założyć, że mają wartość True, jeśli mają niezerową długość, jak lista w Pythonie. Inni mogą chcieć, aby była prawdziwa tylko wtedy, gdy wszystkie jej elementy są prawdziwe. Inni mogą chcieć, aby była prawdziwa, jeśli którykolwiek z jej elementów jest prawdziwy.
Ponieważ istnieje tak wiele sprzecznych oczekiwań, projektanci NumPy i Pandas odmawiają zgadywania i zamiast tego zgłaszają błąd ValueError.
Zamiast tego, trzeba być wyraźny, poprzez wywołanie
empty()
,all()
lubany()
metodę, aby wskazać zachowanie pragnienie.W tym przypadku jednak wygląda na to, że nie chcesz wartościowania boolowskiego, chcesz logicznego i logicznego punktu widzenia . Oto, co
&
wykonuje operator binarny:zwraca tablicę logiczną.
Nawiasem mówiąc, jak zauważa alexpmil , nawiasy są obowiązkowe, ponieważ
&
mają wyższy priorytet operatorów niż==
. Bez nawiasówa['x']==1 & a['y']==10
zostanie oszacowane,a['x'] == (1 & a['y']) == 10
co z kolei byłoby równoważne z połączonym porównaniem(a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10)
. To jest wyraz formySeries and Series
. Użycieand
z dwiema seriami ponownie uruchomiłoby to samo,ValueError
co powyżej. Dlatego nawiasy są obowiązkowe.źródło
x and y
ocenębool(x)
ibool(y)
. Python „najpierw oceniax
; jeślix
ma wartość false, zwracana jest jego wartość; w przeciwnym raziey
jest oceniana i zwracana jest wynikowa wartość”. Tak więc składniax and y
nie może być używana do logicznych elementów, a ponieważ tylkox
luby
może być zwracana. Natomiastx & y
wyzwalaczex.__and__(y)
i__and__
metodę można zdefiniować tak, aby zwracały wszystko, co nam się podoba.==
klauzuli są obowiązkowe .a['x']==1 & a['y']==10
zwraca ten sam błąd co w pytaniu.TLDR; Logika Operatorzy w pandy
&
,|
i~
, i nawiasy(...)
jest ważne!Pythona
and
,or
anot
operatory logiczne są przeznaczone do pracy z skalarów. Dlatego Pandy musiały zrobić coś lepszego i przesłonić operatory bitowe, aby uzyskać wektoryzowaną (elementarną) wersję tej funkcji.A więc następujące w Pythonie (
exp1
iexp2
są to wyrażenia, które dają wynik boolowski) ...... przełoży się na ...
dla pand.
Jeśli w trakcie wykonywania operacji logicznej otrzymasz a
ValueError
, musisz użyć nawiasów do grupowania:Na przykład,
I tak dalej.
Indeksowanie boolowskie : Typową operacją jest obliczanie masek boolowskich na podstawie warunków logicznych w celu filtrowania danych. Pandas udostępnia trzy operatory:
&
logiczne AND,|
logiczne OR i~
logiczne NIE.Rozważ następującą konfigurację:
Logiczne AND
Dla
df
wyżej, że chcesz zwrócić wszystkie wiersze, gdzie A <5 i B> 5. Dokonuje się tego poprzez wyliczenie maski dla każdego warunku oddzielnie, a ich Anding.Przeciążony
&
operator bitowyPrzed kontynuowaniem zwróć uwagę na ten konkretny fragment dokumentacji, który stwierdza
Mając to na uwadze, element mądry logiczne AND można zaimplementować za pomocą operatora bitowego
&
:Kolejny krok filtrowania to po prostu
Nawiasy są używane do przesłonięcia domyślnej kolejności pierwszeństwa operatorów bitowych, które mają wyższy priorytet w stosunku do operatorów warunkowych
<
i>
. Zobacz sekcję Pierwszeństwo operatorów w dokumentacji Pythona.Jeśli nie użyjesz nawiasów, wyrażenie zostanie ocenione niepoprawnie. Na przykład, jeśli przypadkowo spróbujesz czegoś takiego jak
Jest analizowany jako
Który staje się,
Który staje się (zobacz dokumentację Pythona na temat porównania operatorów łańcuchowych ),
Który staje się,
Który rzuca
Więc nie popełniaj tego błędu! 1
Unikanie grupowania w nawiasy
Poprawka jest właściwie dość prosta. Większość operatorów ma odpowiednią metodę powiązaną dla DataFrames. Jeśli poszczególne maski są tworzone przy użyciu funkcji zamiast operatorów warunkowych, nie będzie już konieczne grupowanie według parenów, aby określić kolejność oceny:
Zobacz sekcję dotyczącą elastycznych porównań. . Podsumowując, mamy
Inną opcją unikania nawiasów jest użycie
DataFrame.query
(lubeval
):I obszernie udokumentowane
query
ieval
w dynamicznej oceny ekspresji w pand pomocą pd.eval () .operator.and_
Umożliwia wykonanie tej operacji w funkcjonalny sposób. Połączenia wewnętrzne,
Series.__and__
które odpowiadają operatorowi bitowemu.Zwykle nie będziesz tego potrzebować, ale warto wiedzieć.
Uogólnianie:
np.logical_and
(ilogical_and.reduce
)Inną alternatywą jest użycie
np.logical_and
, które również nie wymaga grupowania w nawiasach:np.logical_and
jest ufunc (funkcje uniwersalne) , a większość ufunc mareduce
metodę. Oznacza to, że łatwiej jest uogólniać,logical_and
jeśli masz wiele masek AND. Na przykład, aby i masekm1
im2
im3
z&
, trzeba by zrobićJednak łatwiejszą opcją jest
Jest to potężne narzędzie, ponieważ pozwala na tworzenie dodatkowych elementów z bardziej złożoną logiką (na przykład dynamiczne generowanie masek w postaci listy i dodawanie ich wszystkich):
1 - Wiem, że dręczy mnie ten punkt, ale proszę o wyrozumiałość. Jest to bardzo , bardzo powszechny błąd początkującego i należy go bardzo dokładnie wyjaśnić.
Logiczne LUB
W
df
powyższym przypadku powiedz, że chcesz zwrócić wszystkie wiersze, w których A == 3 lub B == 7.Przeciążony bitowo
|
Jeśli jeszcze tego nie zrobiłeś, przeczytaj również sekcję o logicznym AND powyżej, wszystkie zastrzeżenia mają tutaj zastosowanie.
Alternatywnie tę operację można określić za pomocą
operator.or_
Wzywa
Series.__or__
pod maską.np.logical_or
W przypadku dwóch warunków użyj
logical_or
:W przypadku wielu masek użyj
logical_or.reduce
:Logiczne NIE
Biorąc pod uwagę maskę, taką jak
Jeśli chcesz odwrócić każdą wartość logiczną (tak, aby wynik końcowy był taki
[False, False, True]
), możesz użyć dowolnej z poniższych metod.Bitowo
~
Ponownie, wyrażenia należy ująć w nawiasy.
To wywołuje wewnętrznie
Ale nie używaj go bezpośrednio.
operator.inv
Wewnętrznie wzywa
__invert__
Serię.np.logical_not
To jest wariant numpy.
Uwaga,
np.logical_and
mogą być podstawionenp.bitwise_and
,logical_or
zbitwise_or
ilogical_not
zinvert
.źródło
|
, które jest równoważnenumpy.bitwise_or
zamiastnumpy.logical_or
. Czy mogę zapytać dlaczego? Czy nie jestnumpy.logical_or
przeznaczony specjalnie do tego zadania? Po co dodawać ciężar robienia tego bitowo dla każdej pary elementów?|
elementów logicznych. Ale dla mnie ta dokumentacja jest bardziej „samouczkiem”, a dla kontrastu czuję, że te odwołania do API są bliższe źródłu prawdy: numpy.bitwise_or i numpy.logical_or - więc staram się zrozumieć, co jest opisane tutaj.Ważne jest, aby zdać sobie sprawę, że nie można użyć dowolnego z pytona operatorów logicznych (
and
,or
lubnot
) napandas.Series
lubpandas.DataFrame
s (podobnie nie można z nich korzystać wnumpy.array
s z więcej niż jednego elementu). Powodem, dla którego nie możesz ich użyć, jest to, że niejawnie wywołują onebool
swoje operandy, które zgłaszają wyjątek, ponieważ te struktury danych zdecydowały, że wartość logiczna tablicy jest niejednoznaczna:Omówiłem to szerzej w mojej odpowiedzi na pytanie „Wartość prawdy serii jest niejednoznaczna. Użyj a.empty, a.bool (), a.item (), a.any () lub a.all ()” Q + A .
Funkcje logiczne NumPys
Jednak NumPy stanowi element mądry odpowiedniki operacyjnego do tych operatorów jak funkcje, które można wykorzystać na
numpy.array
,pandas.Series
,pandas.DataFrame
lub jakiegokolwiek innego (zgodnego)numpy.array
podklasy:and
manp.logical_and
or
manp.logical_or
not
manp.logical_not
numpy.logical_xor
który nie ma odpowiednika w Pythonie, ale jest operacją logiczną „wyłączną”Zasadniczo więc należy użyć (zakładając
df1
idf2
są pandami DataFrames):Funkcje bitowe i operatory bitowe dla wartości logicznych
Jednak w przypadku, gdy masz tablicę logiczną NumPy, serię pandy lub pandy DataFrames, możesz również użyć funkcji bitowych z uwzględnieniem elementów (dla wartości logicznych są one - lub przynajmniej powinny być - nie do odróżnienia od funkcji logicznych):
np.bitwise_and
lub&
operatornp.bitwise_or
lub|
operatornp.invert
(lub aliasnp.bitwise_not
) lub~
operatornp.bitwise_xor
lub^
operatorZwykle używane są operatory. Jednak w połączeniu z operatorami porównania należy pamiętać o zawinięciu porównania w nawiasach, ponieważ operatory bitowe mają wyższy priorytet niż operatory porównania :
Może to być irytujące, ponieważ operatory logiczne Pythona mają mniejszą dokładność niż operatory porównania, więc zwykle piszesz
a < 10 and b > 10
(gdziea
ib
są to na przykład proste liczby całkowite) i nie potrzebujesz nawiasów.Różnice między operacjami logicznymi i bitowymi (w przypadku operacji innych niż logiczne)
Naprawdę ważne jest, aby podkreślić, że operacje bitowe i logiczne są równoważne tylko dla tablic logicznych NumPy (oraz logicznych Series i DataFrames). Jeśli nie zawierają one wartości logicznych, operacje dadzą różne wyniki. Podam przykłady wykorzystujące tablice NumPy, ale wyniki będą podobne dla struktur danych pandy:
A ponieważ NumPy (i podobnie pandy) robi różne rzeczy dla indeksów boolowskich ( tablice indeksowe Boolean lub „maski” ) i całkowitych ( tablice indeksowe ), wyniki indeksowania również będą inne:
Tabelka podsumowująca
Gdzie operator logiczny nie działa dla tablic NumPy , pandas Series i pandas DataFrames. Pozostali pracują na tych strukturach danych (i zwykłych obiektach Pythona) i pracują na elementach. Należy jednak zachować ostrożność przy odwracaniu bitów w zwykłym Pythonie,
bool
ponieważ bool zostanie zinterpretowany jako liczby całkowite w tym kontekście (na przykład~False
zwraca-1
i~True
zwraca-2
).źródło