Logische Operatoren für Boolesche Indexierung Pandas
Arbeite ich mit boolean-index in der Pandas.
Die Frage ist, warum die Aussage:
a[(a['some_column']==some_number) & (a['some_other_column']==some_other_number)]
funktioniert in der Erwägung, dass
a[(a['some_column']==some_number) and (a['some_other_column']==some_other_number)]
beendet sich mit Fehler?
Beispiel:
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()
- Dies ist, weil numpy-arrays und pandas-Serie verwenden Sie den bitweisen Operatoren anstatt logisch wie Sie vergleichen jedes element im array/Serien mit einem anderen. Es ist daher nicht sinnvoll, so verwenden Sie den logischen operator in dieser situation. siehe Verwandte: stackoverflow.com/questions/8632033/...
- In Python
and != &
. Dieand
- operator in Python nicht überschrieben werden kann, in der Erwägung, dass die&
operator (__and__
) kann. Daher die Wahl der Verwendung&
in numpy und pandas. - Verwandte: Wahrheitswert einer Serie ist mehrdeutig. Verwenden Sie einen.leer, ein.bool(), ein.Element(), ein.jede() oder eine.alle()
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie sagen,
Sind Sie implizit Fragen, Python zu konvertieren
(a['x']==1)
und(a['y']==10)
boolean-Werte.NumPy-arrays (mit einer Länge größer als 1) und Pandas Objekte wie Serie nicht über ein boolean-Wert -- in anderen Worten, Sie erhöhen
als booleschen Wert. Das ist, weil seine unklar, Wann es sein sollte True oder False. Einige Benutzer könnten annehmen, dass Sie Wahr sind, wenn Sie nicht die Länge null, wie ein Python-Liste. Andere wünschen es werden nur Wahr, wenn alle Ihre Elemente Wahr sind. Andere wollen es, um Wahr zu sein, wenn alle Ihre Elemente Wahr sind.
Weil es so viele widersprüchliche Erwartungen, die Designer von NumPy und Pandas verweigern, zu erraten, und anstatt aufwerfen einen ValueError.
Stattdessen müssen Sie explizit durch Aufruf der
empty()
,all()
oderany()
Methode zu zeigen, welches Verhalten Sie wünschen.In diesem Fall, jedoch, es sieht aus wie Sie nicht möchten, dass Boolesche Auswertung, die Sie wollen element-wise logisch-und. Das ist das, was die
&
binary-operator führt:gibt einen boolean-array.
Durch die Art und Weise, wie alexpmil Noten,
die Klammern sind zwingend erforderlich, da
&
hat eine höhere operator-Rangfolge als==
.Ohne die Klammern
a['x']==1 & a['y']==10
bewertet alsa['x'] == (1 & a['y']) == 10
was sich wiederum entspricht dem verketteten Vergleich(a['x'] == (1 & a['y'])) and ((1 & a['y']) == 10)
. Das ist ein Ausdruck der formSeries and Series
.Die Verwendung von
and
mit zwei Serien würde wieder auslösen das gleicheValueError
wie oben. Das ist, warum sind die Klammern zwingend.x and y
löst die Auswertung derbool(x)
undbool(y)
. Python "first wertetx
; wennx
false ist, wird dessen Wert zurückgegeben; anderenfallsy
ausgewertet und der resultierende Wert wird zurückgegeben." Also die syntaxx and y
können nicht verwendet werden für-element-wised logisch-und da nurx
odery
zurückgegeben werden können. Im Gegensatz dazux & y
löstx.__and__(y)
und die__and__
Methode kann definiert werden, alles zurückzugeben, was wir mögen.==
Klausel sind obligatorisch.a['x']==1 & a['y']==10
wieder die gleichen Fehler wie in der Frage.or
Betreiber. Python-Betreiber Google docs finden Sie hier.TLDR; Logische Operatoren in Pandas sind
&
,|
und~
, und Klammern(...)
ist wichtig!Python ' s
and
,or
undnot
logische Operatoren arbeiten mit skalaren. Also Pandas zu tun hatten, ein besseres und überschreiben Sie die bitweisen Operatoren zu erreichen vektorisiert (element-wise) version dieser Funktion.Also Folgendes in python (
exp1
undexp2
sind Ausdrücke, die zu einem booleschen Wert ausgewertet-Ergebnis)......wird übersetzt zu...
für pandas.
Wenn in den Prozess der Durchführung von logischen operation erhalten Sie eine
ValueError
, dann müssen Sie die Verwendung von Klammern zum gruppieren von:Beispielsweise
Und so weiter.
Boolean Indizierung: Eine gemeinsame operation ist zur Berechnung boolescher Masken durch die logischen Bedingungen zum filtern der Daten. Pandas bietet drei Betreiber:
&
für das logische UND,|
für das logische ODER und~
für logische NICHT.Betrachten Sie das folgende setup:
Logische UND
Für
df
oben, sagen Sie, Sie möchten alle Zeilen, wo A < 5 B > 5. Dies geschieht mittels EDV-Masken für jede Bedingung separat, und-Verknüpfung Sie.Überlastet Bitweise
&
BetreiberBevor Sie fortfahren, beachten Sie bitte die diesem bestimmten Auszug aus den docs, die Staatliche
So, in diesem Sinne, element-Weise logisches UND können umgesetzt werden mit dem bitweisen operator
&
:Und die Filterung Schritt ist einfach,
Den Klammern werden verwendet, um die Standardeinstellung zu überschreiben Rangfolge der bitweisen Operatoren aus, die höhere Priorität über die bedingte Operatoren
<
und>
. Siehe den Abschnitt Operator-Rangfolge in die python docs.Wenn Sie keine Klammern verwenden, wird der Ausdruck falsch ausgewertet wird. Zum Beispiel, wenn Sie versehentlich versuchen, so etwas wie
Es wird analysiert, wie
Wird,
Wird (siehe die python docs auf verkettet operator Vergleich),
Wird,
Die wirft
Also, machen Sie nicht diesen Fehler!1
Vermeidung Von Klammern Gruppieren
Die Lösung ist eigentlich ganz einfach. Die meisten Anbieter haben eine entsprechende gebundene Methode für DataFrames. Wenn die einzelnen Masken aufgebaut werden mit Funktionen anstelle von bedingten Operatoren, die Sie nicht mehr benötigen, um die Gruppe von Klammern, um anzugeben, Bewertung Reihenfolge:
Siehe den Abschnitt über Flexible Vergleiche.. Um zusammenzufassen, wir haben
Weitere option zur Vermeidung von Klammern ist die Verwendung
DataFrame.query
(odereval
):Habe ich ausgiebig dokumentiert
query
undeval
im Dynamische Auswertung eines Ausdrucks in pandas mit pd.eval().- operator.and_
Können Sie führen diesen Vorgang in einer funktionellen Art und Weise. Intern ruft
Series.__and__
das entspricht dem bitweisen operator.Sie in der Regel nicht brauchen, aber es ist nützlich zu wissen.
Verallgemeinern:
np.logical_and
(undlogical_and.reduce
)Eine weitere alternative ist die Verwendung
np.logical_and
, der braucht auch keine Klammern gruppieren:np.logical_and
ist ein ufunc (Universal Funktion), und die meisten ufuncs haben einereduzieren
Methode. Dies bedeutet, dass es einfacher ist, zu verallgemeinern, mitlogical_and
wenn Sie mehrere Masken UND. Zum Beispiel, UND Maskenm1
undm2
undm3
mit&
Sie zu tun habenJedoch eine einfachere Möglichkeit ist
Dieser ist mächtig, weil es Ihnen ermöglicht, bauen auf diesem mit komplexer Logik (zum Beispiel der dynamischen Generierung von Masken in der Liste das Verständnis und das hinzufügen alle von Ihnen):
1 - ich weiß, ich bin herumreiten auf diesem Punkt, aber bitte Geduld mit mir. Dies ist ein sehr, sehr häufige Anfängerfehler, und muss erklärt werden, sehr gründlich.
Logische ODER
Für die
df
oben, sagen Sie, dass Sie möchten, um alle Zeilen, in denen A == 3 oder B == 7.Überlastet Bitweise
|
Falls Sie es noch nicht, Lesen Sie bitte auch den Abschnitt über Logische UND oben, alle Vorbehalte gelten hier.
Alternativ kann dieser Vorgang angegeben werden, mit
- operator.or_
Anrufe
Series.__or__
unter der Haube.np.logical_or
Für die zwei Bedingungen, verwenden Sie
logical_or
:Für mehrere Masken verwenden
logical_or.reduce
:Logisch NICHT
Gegeben, eine Maske, wie
Wenn Sie müssen umkehren, jeder booleschen Wert (so dass das end-Ergebnis ist
[False, False, True]
), dann Sie können verwenden Sie eine der folgenden Methoden.Bitweise
~
Wieder Ausdrücke sein müssen, parenthesised.
Dieser ruft intern
Aber verwenden Sie es nicht direkt.
operator.inv
Intern ruft
__invert__
auf die Reihe.np.logical_not
Dies ist die numpy-Variante.
Hinweis,
np.logical_and
ausgetauscht werden können, fürnp.bitwise_and
,logical_or
mitbitwise_or
, undlogical_not
mitinvert
.|
entsprichtnumpy.bitwise_or
stattnumpy.logical_or
. Darf ich Fragen, warum? Nichtnumpy.logical_or
speziell für diese Aufgabe speziell? Warum sollten Sie die Last, es zu tun, bitweise für jedes paar von Elementen?|
für element-wise booleschen operation. Aber für mich, dass die Dokumentation ist mehr ein "tutorial", und im Gegensatz, ich fühle mich mit diesen API-Referenzen sind näher an der Quelle der Wahrheit: numpy.bitwise_or und numpy.logical_or - so bin ich versucht zu verstehen, was hier beschrieben wird.numpy.bitwise_or
entspricht|
. Aber Sie sagen nichtnumpy.bitwise_or
ist funktionell äquivalent zunumpy.logical_or
. Wie können wir also sicher sein, dass Sie sind? Die erstere ist eine bitweise operation nicht also es hängt von NumPy ist die binäre Darstellung der booleschen Werte?bool
. Ansonsten, du hast Recht. Probieren Sie es aus:np.bitwise_not([False])
versusnp.bitwise_not(np.array([False], dtype=object))
bitwise_xor
, und es scheint, daß diese bitweisen Operatoren nicht blind auf allen bits - er überprüft auch die Art, wie Sie erwähnt; wenn esnp._bool
es ist "smart" genug, um zu wissen, zu bedienen nur die sinnvolle bisschen. So, zurück zu meinem ursprünglichen Punkt: ich sehe jetzt, für Boolean-element-Weise Operationen|
undnumpy.bitwise_or
sind äquivalent zunumpy.logical_or
, und|
ist wahrscheinlich bevorzugt durch lapidare.Ist es wichtig zu erkennen, dass Sie nicht verwenden die Python logische Operatoren (
and
,or
odernot
) aufpandas.Series
oderpandas.DataFrame
s (ähnlich wie man nicht aufnumpy.array
s mit mehr als einem element). Der Grund, warum Sie nicht verwenden können, diejenigen, die, weil Sie implizit nennenbool
auf Ihre Operanden, die eine Ausnahme wirft, denn diese Datenstrukturen entschieden, dass das boolean-array aber ist zweideutig:Habe ich diese noch Ausführlicher in meiner Antwort auf die "Wahrheit Wert einer Folge ist eindeutig. Verwenden Sie einen.leer, ein.bool(), ein.Element(), ein.jede() oder eine.alle()" Q+A.
NumPys logische Funktionen
Jedoch NumPy bietet element-wise Betriebs-äquivalente für diese Operatoren als Funktionen, die verwendet werden können, die auf
numpy.array
,pandas.Series
,pandas.DataFrame
oder andere (konforme)numpy.array
Unterklasse:and
hatnp.logical_and
or
hatnp.logical_or
not
hatnp.logical_not
numpy.logical_xor
, die keine Python-äquivalent, sondern ist eine logische "exklusives oder" BetriebSo, im wesentlichen, sollte man Sie nutzen (vorausgesetzt
df1
unddf2
sind pandas DataFrames):Bitweise Funktionen und bitweise Operatoren für boolsche Variablen
Jedoch in Fall müssen Sie Boolesche NumPy-array, pandas Serie, oder pandas DataFrames können Sie auch das element-Weise bitweise Funktionen (für booleans Sie sind - oder zumindest sein sollte - nicht von den logischen Funktionen):
np.bitwise_and
oder die&
Betreibernp.bitwise_or
oder die|
Betreibernp.invertieren
(oder den aliasnp.bitwise_not
) oder die~
Betreibernp.bitwise_xor
oder die^
BetreiberIn der Regel der Betreiber verwendet werden. Allerdings, wenn in Kombination mit Vergleichsoperatoren daran zu erinnern, um wickeln Sie den Vergleich in Klammern, weil die bitweisen Operatoren haben eine höhere Priorität als die Vergleichsoperatoren:
Diese kann irritierend sein, weil das Python-logische Operatoren haben eine niedrigere precendence als die Vergleichsoperatoren, so dass Sie normalerweise schreiben
a < 10 and b > 10
(woa
undb
sind zum Beispiel einfache Ganzzahlen) und brauchen nicht die Klammer.Unterschiede zwischen logischen und bitweisen Operationen (auf nicht-Boolesche Werte)
Es ist wirklich wichtig zu betonen, dass die bit-und logischen Operationen sind nur äquivalent für "boolean" NumPy-arrays (und boolean-Serie & DataFrames). Wenn diese nicht enthalten Boolesche Werte dann bei den Operationen zu unterschiedlichen Ergebnissen führen. Ich werde auch Beispiele, die über NumPy arrays, aber die Ergebnisse werden ähnlich wie bei den pandas Datenstrukturen:
Und da NumPy (und ähnlich pandas) macht verschiedene Dinge für boolean (Boolean oder "Maske" index-arrays) und integer (Index-arrays) Indizes, die die Ergebnisse der Indexierung wird auch anders sein:
Zusammenfassung Tabelle
Wo den logischen operator funktioniert nicht bei NumPy-arrays, pandas Serie und pandas DataFrames. Die anderen arbeiten, die auf diesen Datenstrukturen (und plain Python-Objekte) und element-Weise.
Seien Sie jedoch vorsichtig mit der bitweisen invertieren auf plain Python
bool
s, weil die bool interpretiert werden als Ganzzahlen in diesem Zusammenhang (zum Beispiel~False
zurück-1
und~True
zurück-2
).