it-swarm.com.de

Der Wahrheitswert einer Serie ist nicht eindeutig. Verwenden Sie a.empty, a.bool (), a.item (), a.any () oder a.all ()

Beim Filtern meines Ergebnisdatenrahmens mit der Bedingung or ist ein Fehler aufgetreten. Ich möchte, dass mein Ergebnis df alle Werte der Spalte var extrahiert, die über 0,25 und unter -0,25 liegen.

Diese Logik unten gibt mir einen mehrdeutigen Wahrheitswert. Sie funktioniert jedoch, wenn ich diese Filterung in zwei separate Operationen aufteile. Was passiert hier? Ich bin mir nicht sicher, wo ich die vorgeschlagene a.empty(), a.bool(), a.item(),a.any() or a.all() verwenden soll.

 result = result[(result['var']>0.25) or (result['var']<-0.25)]
239
obabs

Die Anweisungen or und and python erfordern truth- Werte. Für pandas gelten diese als mehrdeutig, daher sollten Sie "bitweise" _|_ (oder) oder _&_ (und) verwenden:

_result = result[(result['var']>0.25) | (result['var']<-0.25)]
_

Diese werden für diese Art von Datenstrukturen überladen, um das elementweise or (oder and) zu ergeben.


Nur um dieser Aussage eine Erklärung hinzuzufügen:

Die Ausnahme wird ausgelöst, wenn Sie bool eines _pandas.Series_ abrufen möchten:

_>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
_

Was Sie getroffen haben, war eine Stelle, an der der Operator implizit die Operanden in bool konvertierte (Sie haben or verwendet, aber es passiert auch für and, if und while):

_>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
_

Neben diesen 4 Anweisungen gibt es mehrere python Funktionen, die einige bool Aufrufe verbergen (wie any, all, filter, ...) Normalerweise kein Problem mit _pandas.Series_, aber der Vollständigkeit halber wollte ich diese erwähnen.


In Ihrem Fall ist die Ausnahme nicht wirklich hilfreich, da die richtigen Alternativen nicht erwähnt werden. Für and und or können Sie Folgendes verwenden (wenn Sie elementweise Vergleiche wünschen):

  • numpy.logical_or :

    _>>> import numpy as np
    >>> np.logical_or(x, y)
    _

    oder einfach der Operator _|_:

    _>>> x | y
    _
  • numpy.logical_and :

    _>>> np.logical_and(x, y)
    _

    oder einfach der Operator _&_:

    _>>> x & y
    _

Wenn Sie die Operatoren verwenden, stellen Sie sicher, dass Sie Ihre Klammern aufgrund von Operatorrangfolge richtig gesetzt haben.

Es gibt mehrere logische Zahlenfunktionen welche an _pandas.Series_ arbeiten sollen .


Die in der Ausnahme genannten Alternativen sind besser geeignet, wenn Sie sie beim Ausführen von if oder while kennen. Ich werde kurz jede dieser erklären:

  • Wenn Sie überprüfen möchten, ob Ihre Serie leer ist:

    _>>> x = pd.Series([])
    >>> x.empty
    True
    >>> x = pd.Series([1])
    >>> x.empty
    False
    _

    Python interpretiert normalerweise das length von Containern (wie list, Tuple, ...) als Wahrheitswert, wenn es keine explizite boolesche Interpretation hat. Wenn Sie also die pythonähnliche Prüfung möchten, können Sie Folgendes ausführen: _if x.size_ oder _if not x.empty_ anstelle von _if x_.

  • Wenn Ihr Series ein und nur ein Boolescher Wert enthält:

    _>>> x = pd.Series([100])
    >>> (x > 50).bool()
    True
    >>> (x < 50).bool()
    False
    _
  • Wenn Sie als erstes und einziges Element Ihrer Serie prüfen möchten (wie .bool(), funktioniert aber auch für nicht-boolesche Inhalte):

    _>>> x = pd.Series([100])
    >>> x.item()
    100
    _
  • Wenn Sie überprüfen möchten, ob all oder any item nicht null, nicht leer oder nicht falsch ist:

    _>>> x = pd.Series([0, 1, 2])
    >>> x.all()   # because one element is zero
    False
    >>> x.any()   # because one (or more) elements are non-zero
    True
    _
399
MSeifert

Verwenden Sie für die Boolesche Logik & und |.

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))

>>> df
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

Um zu sehen, was passiert, erhalten Sie für jeden Vergleich eine Spalte mit Booleschen Werten, z.

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool

Wenn Sie mehrere Kriterien haben, werden mehrere Spalten zurückgegeben. Aus diesem Grund ist die Verknüpfungslogik nicht eindeutig. Wenn Sie and oder or verwenden, wird jede Spalte separat behandelt. Daher müssen Sie diese Spalte zunächst auf einen einzigen booleschen Wert reduzieren. Zum Beispiel, um zu sehen, ob ein Wert oder alle Werte in jeder der Spalten True sind.

# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True

# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False

Ein komplizierter Weg, um dasselbe zu erreichen, besteht darin, alle diese Spalten zu komprimieren und die entsprechende Logik auszuführen.

>>> df[[any([a, b]) for a, b in Zip(df.C > 0.25, df.C < -0.25)]]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

Weitere Informationen finden Sie in den Dokumenten unter Boolean Indexing .

31
Alexander

Alternativ können Sie auch das Operator-Modul verwenden. Weitere Informationen finden Sie hier Python-Dokumente

import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C > 0.25, df.C < -0.25)]

          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.4438

Diese ausgezeichnete Antwort erklärt sehr gut, was passiert und bietet eine Lösung. Ich möchte eine andere Lösung hinzufügen, die in ähnlichen Fällen geeignet sein könnte: Verwenden der query -Methode:

result = result.query("(var > 0.25) or (var < -0.25)")

Siehe auch http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query .

(Einige Tests mit einem Datenrahmen, mit dem ich gerade arbeite, legen nahe, dass diese Methode etwas langsamer ist als die Verwendung der bitweisen Operatoren für Reihen von Booleschen Werten: 2 ms gegenüber 870 µs.)

Eine Warnung : Mindestens eine Situation, in der dies nicht einfach ist, ist, wenn Spaltennamen zufällig python Ausdrücke sind. Ich hatte Spalten mit den Namen WT_38hph_IP_2, WT_38hph_input_2 und log2(WT_38hph_IP_2/WT_38hph_input_2) und wollte die folgende Abfrage ausführen: "(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

Ich habe die folgende Ausnahmekaskade erhalten:

  • KeyError: 'log2'
  • UndefinedVariableError: name 'log2' is not defined
  • ValueError: "log2" is not a supported function

Ich schätze, das ist passiert, weil der Abfrage-Parser versucht hat, etwas aus den ersten beiden Spalten zu machen, anstatt den Ausdruck mit dem Namen der dritten Spalte zu identifizieren.

Eine mögliche Problemumgehung wird vorgeschlagen hier .

1
bli