it-swarm.com.de

FutureWarning: Elementweiser Vergleich fehlgeschlagen; Skalar zurückgeben, wird aber in der Zukunft einen elementaren Vergleich durchführen

Ich verwende Pandas 0.19.1 für Python 3. Ich bekomme eine Warnung zu diesen Codezeilen. Ich versuche, eine Liste zu erhalten, die alle Zeilennummern enthält, in denen die Zeichenfolge Peter in Spalte Unnamed: 5 vorhanden ist.

df = pd.read_Excel(xls_path)
myRows = df[df['Unnamed: 5'] == 'Peter'].index.tolist()

Warnung:

"\Python36\lib\site-packages\pandas\core\ops.py:792: FutureWarning: elementwise 
comparison failed; returning scalar, but in the future will perform 
elementwise comparison 
result = getattr(x, name)(y)"

Was ist das für FutureWarning und sollte ich es ignorieren, da es scheinbar funktioniert? 

26
Arturo

Diese FutureWarning stammt nicht von Pandas, sie ist von Numpy und der Fehler wirkt sich auch auf Matplotlib und andere aus. So wird die Warnung näher an der Ursache des Problems reproduziert:

import numpy as np
print(np.__version__)   # Numpy version '1.12.0'
'x' in np.arange(5)       #Future warning thrown here

FutureWarning: elementwise comparison failed; returning scalar instead, but in the 
future will perform elementwise comparison
False

Eine andere Möglichkeit, diesen Fehler mithilfe des Double-Equals-Operators zu reproduzieren:

import numpy as np
np.arange(5) == np.arange(5).astype(str)    #FutureWarning thrown here

Ein Beispiel für Matplotlib, das von dieser FutureWarning-Implementierung in der Köcher-Plot-Implementierung betroffen ist: https://matplotlib.org/examples/pylab_examples/quiver_demo.html

Was ist denn hier los?

Es gibt eine Meinungsverschiedenheit zwischen Numpy und nativem Python, was passieren soll, wenn Sie einen String mit numerischen Typen von Numpy vergleichen. Beachten Sie, dass der linke Operand Pythons Rasen ist, eine primitive Zeichenfolge, und die mittlere Operation ist Pythons Rasen, aber der rechte Operand ist der Rasen von Numpy. Solltest du einen Python-Style Scalar oder einen Numpy-Stil von Boolean zurückgeben? Numpy sagt Narrarr von Bool, die Entwickler von Pythonic sind anderer Meinung. Klassischer Abstand.

Sollte es sich um einen elementweisen Vergleich oder um einen Skalar handeln, wenn ein Element im Array vorhanden ist? 

Wenn Ihr Code oder Ihre Bibliothek die Operatoren in oder == verwendet, um die Python-Zeichenfolge mit numpy ndarrays zu vergleichen, sind sie nicht kompatibel. Wenn Sie dies versuchen, wird ein Skalar zurückgegeben. Die Warnung weist darauf hin, dass sich dieses Verhalten in der Zukunft ändern kann. Wenn sich Python/Numpy für den Modus "Numpy" entscheidet, kotzt Ihr Code auf dem gesamten Teppich. 

Übermittelte Fehlerberichte:

Numpy und Python befinden sich in einer Pattsituation, für den Moment gibt die Operation einen Skalar zurück, aber in der Zukunft kann sich dies ändern.

https://github.com/numpy/numpy/issues/6784

https://github.com/pandas-dev/pandas/issues/7830

Zwei Problemumgehungslösungen:

Sperren Sie entweder Ihre Version von Python und Numpy und ignorieren Sie die Warnungen, oder setzen Sie Ihre linken und rechten Operanden so ein, dass sie von einem gemeinsamen Rasen stammen.

Unterdrücken Sie die Warnung global:

import warnings
import numpy as np
warnings.simplefilter(action='ignore', category=FutureWarning)
print('x' in np.arange(5))   #returns False, without Warning

Unterdrücken Sie die Warnung Zeile für Zeile.

import warnings
import numpy as np

with warnings.catch_warnings():
    warnings.simplefilter(action='ignore', category=FutureWarning)
    print('x' in np.arange(2))   #returns False, warning is suppressed

print('x' in np.arange(10))   #returns False, Throws FutureWarning

Unterdrücken Sie einfach die Warnung anhand des Namens und fügen Sie einen lauten Kommentar hinzu, in dem die aktuelle Version von Python und Numpy erwähnt wird. Dieser Code ist spröde und erfordert diese Versionen und einen Link zu diesem Link. Treten Sie die Dose die Straße hinunter.

39
Eric Leschinski

Meine Erfahrung mit derselben Warnmeldung wurde durch TypeError verursacht.

TypeError: ungültiger Typvergleich

Vielleicht möchten Sie den Datentyp des Unnamed: 5 überprüfen.

for x in df['Unnamed: 5']:
  print(type(x))  # are they 'str' ?

So kann ich die Warnmeldung replizieren: 

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(3, 2), columns=['num1', 'num2'])
df['num3'] = 3
df.loc[df['num3'] == '3', 'num3'] = 4  # TypeError and the Warning
df.loc[df['num3'] == 3, 'num3'] = 4  # No Error

Ich hoffe es hilft.

1
yhd.leung

Ich erhalte dieselbe Fehlermeldung, wenn ich versuche, den index_col beim Lesen einer Datei in den Datenrahmen einer Panda zu setzen:

df = pd.read_csv('my_file.tsv', sep='\t', header=0, index_col=['0'])  ## or same with the following
df = pd.read_csv('my_file.tsv', sep='\t', header=0, index_col=[0])

Ich bin noch nie zuvor auf einen solchen Fehler gestoßen. Ich versuche immer noch, den Grund dafür herauszufinden (unter Verwendung der Erklärung von @Eric Leschinski und anderen).

Auf jeden Fall löst der folgende Ansatz das Problem vorerst, bis ich den Grund herausfinde:

df = pd.read_csv('my_file.tsv', sep='\t', header=0)  ## not setting the index_col
df.set_index(['0'], inplace=True)

Ich werde dies aktualisieren, sobald ich den Grund für ein solches Verhalten herausgefunden habe. 

1
Dataman

Ich habe diese Warnung erhalten, weil ich dachte, meine Spalte enthielt Nullzeichenfolgen, aber beim Überprüfen enthielt sie np.nan!

if df['column'] == '':

Das Ändern meiner Spalte in leere Zeichenfolgen hat geholfen :)

0
intotecho

Ich habe einige der hierfür möglichen Methoden verglichen, darunter Pandas, verschiedene Numpy-Methoden und eine Listenerfassungsmethode.

Beginnen wir zunächst mit einer Grundlinie:

>>> import numpy as np
>>> import operator
>>> import pandas as pd

>>> x = [1, 2, 1, 2]
>>> %time count = np.sum(np.equal(1, x))
>>> print("Count {} using numpy equal with ints".format(count))
CPU times: user 52 µs, sys: 0 ns, total: 52 µs
Wall time: 56 µs
Count 2 using numpy equal with ints

Wir gehen also davon aus, dass die Zählung korrekt sein sollte 2 Und wir sollten ungefähr 50 us Nehmen.

Nun versuchen wir die naive Methode:

>>> x = ['s', 'b', 's', 'b']
>>> %time count = np.sum(np.equal('s', x))
>>> print("Count {} using numpy equal".format(count))
CPU times: user 145 µs, sys: 24 µs, total: 169 µs
Wall time: 158 µs
Count NotImplemented using numpy equal
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/ipykernel_launcher.py:1: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
  """Entry point for launching an IPython kernel.

Und hier erhalten wir die falsche Antwort (NotImplemented != 2), Es dauert lange und es gibt eine Warnung aus.

Also werden wir eine andere naive Methode ausprobieren:

>>> %time count = np.sum(x == 's')
>>> print("Count {} using ==".format(count))
CPU times: user 46 µs, sys: 1 µs, total: 47 µs
Wall time: 50.1 µs
Count 0 using ==

Wieder die falsche Antwort (0 != 2). Dies ist umso heimtückischer, als es keine nachfolgenden Warnungen gibt (0 Kann genauso herumgereicht werden wie 2).

Versuchen wir nun ein Listenverständnis:

>>> %time count = np.sum([operator.eq(_x, 's') for _x in x])
>>> print("Count {} using list comprehension".format(count))
CPU times: user 55 µs, sys: 1 µs, total: 56 µs
Wall time: 60.3 µs
Count 2 using list comprehension

Wir bekommen hier die richtige Antwort und es geht ziemlich schnell!

Eine andere Möglichkeit, pandas:

>>> y = pd.Series(x)
>>> %time count = np.sum(y == 's')
>>> print("Count {} using pandas ==".format(count))
CPU times: user 453 µs, sys: 31 µs, total: 484 µs
Wall time: 463 µs
Count 2 using pandas ==

Langsam, aber richtig!

Und schließlich die Option, die ich verwenden werde: Umwandlung des Arrays numpy in den Typ object:

>>> x = np.array(['s', 'b', 's', 'b']).astype(object)
>>> %time count = np.sum(np.equal('s', x))
>>> print("Count {} using numpy equal".format(count))
CPU times: user 50 µs, sys: 1 µs, total: 51 µs
Wall time: 55.1 µs
Count 2 using numpy equal

Schnell und richtig!

0
ahagen

Wenn Ihre Arrays nicht zu groß sind oder Sie nicht zu viele davon haben, können Sie möglicherweise die linke Seite von == als Zeichenfolge erzwingen:

myRows = df[str(df['Unnamed: 5']) == 'Peter'].index.tolist()

Dies ist jedoch ~ 1,5-mal langsamer, wenn df['Unnamed: 5'] eine Zeichenfolge ist, 25-30-mal langsamer, wenn df['Unnamed: 5'] ein kleines numpy-Array (length = 10) ist, und 150-160-mal langsamer, wenn es sich um ein numpy-Array mit der Länge 100 handelt (mal im Durchschnitt über 500) Versuche).

a = linspace(0, 5, 10)
b = linspace(0, 50, 100)
n = 500
string1 = 'Peter'
string2 = 'blargh'
times_a = zeros(n)
times_str_a = zeros(n)
times_s = zeros(n)
times_str_s = zeros(n)
times_b = zeros(n)
times_str_b = zeros(n)
for i in range(n):
    t0 = time.time()
    tmp1 = a == string1
    t1 = time.time()
    tmp2 = str(a) == string1
    t2 = time.time()
    tmp3 = string2 == string1
    t3 = time.time()
    tmp4 = str(string2) == string1
    t4 = time.time()
    tmp5 = b == string1
    t5 = time.time()
    tmp6 = str(b) == string1
    t6 = time.time()
    times_a[i] = t1 - t0
    times_str_a[i] = t2 - t1
    times_s[i] = t3 - t2
    times_str_s[i] = t4 - t3
    times_b[i] = t5 - t4
    times_str_b[i] = t6 - t5
print('Small array:')
print('Time to compare without str conversion: {} s. With str conversion: {} s'.format(mean(times_a), mean(times_str_a)))
print('Ratio of time with/without string conversion: {}'.format(mean(times_str_a)/mean(times_a)))

print('\nBig array')
print('Time to compare without str conversion: {} s. With str conversion: {} s'.format(mean(times_b), mean(times_str_b)))
print(mean(times_str_b)/mean(times_b))

print('\nString')
print('Time to compare without str conversion: {} s. With str conversion: {} s'.format(mean(times_s), mean(times_str_s)))
print('Ratio of time with/without string conversion: {}'.format(mean(times_str_s)/mean(times_s)))

Ergebnis:

Small array:
Time to compare without str conversion: 6.58464431763e-06 s. With str conversion: 0.000173756599426 s
Ratio of time with/without string conversion: 26.3881526541

Big array
Time to compare without str conversion: 5.44309616089e-06 s. With str conversion: 0.000870866775513 s
159.99474375821288

String
Time to compare without str conversion: 5.89370727539e-07 s. With str conversion: 8.30173492432e-07 s
Ratio of time with/without string conversion: 1.40857605178
0
EL_DON

Eine schnelle Abhilfe hierfür ist die Verwendung von numpy.core.defchararray. Ich war auch mit der gleichen Warnmeldung konfrontiert und konnte sie mit dem obigen Modul beheben.

import numpy.core.defchararray as npd
resultdataset = npd.equal(dataset1, dataset2)
0
Jeet23