FutureWarning: la comparaison élémentaire a échoué; retour scalaire, mais à l'avenir effectuera la comparaison élémentaire

j'utilise Pandas 0.19.1 sur Python 3. Je reçois un avertissement sur ces lignes de code. J'essaie d'obtenir une liste qui contient tous les numéros de ligne où string Peter est présent à la colonne Unnamed: 5.

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

attention:

"Python36libsite-packagespandascoreops.py:792: FutureWarning: elementwise 
comparison failed; returning scalar, but in the future will perform 
elementwise comparison 
result = getattr(x, name)(y)"

Qu'est-ce que cette mise en garde futuriste et devrais-je l'ignorer puisque cela semble fonctionner.

19
demandé sur Eric Leschinski 2016-11-17 18:46:33

5 réponses

ce FutureWarning n'est pas de Pandas, il est de numpy et le bug affecte aussi matplotlib et d'autres, voici comment reproduire l'avertissement plus proche de la source du problème:

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

une autre façon de reproduire ce bug en utilisant l'opérateur double égale:

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

un exemple de Matplotlib affecté par ce FutureWarning dans le cadre de leur implémentation de Quiver plot: https://matplotlib.org/examples/pylab_examples/quiver_demo.html

Ce qu'il se passe ici?

il y a un désaccord entre Numpy et natif python sur ce qui devrait se passer quand vous comparez une chaîne aux types numériques de numpy. Remarquez que l'opérande de gauche est le gazon de python, une chaîne primitive, et l'opération du milieu est le gazon de python, mais l'opérande de droite est le gazon de nompy. Devez-vous retourner un Scalar de style Python ou un ndarray de style num Py de booléen? Numpy dit que ndarray de bool, les développeurs Pythoniques ne sont pas d'accord. Une confrontation classique.

devrait-il s'agir d'une comparaison élémentaire ou scalaire si l'élément existe dans le tableau?

si votre code ou votre bibliothèque utilise le in ou == opérateurs de comparer python chaîne de numpy ndarrays, ils ne sont pas compatibles, donc si vous l'essayez, il retourne un scalaire, mais uniquement pour l'instant. L'avertissement indique que dans le futur ce comportement pourrait changer de sorte que votre code vomit partout sur le tapis si python / numpy décident d'adopter le style Numpy.

rapports de bogues soumis:

Numpy et Python sont dans une impasse, pour l'instant, l'opération retourne un scalaire, mais dans l'avenir, il peut changer.

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

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

deux solutions de contournement:

soit verrouiller votre version de python et de numpy et ignorer les avertissements, ou gardez vos opérandes gauche et droite pour être d'un terrain commun.

Supprimer l'avertissement globalement:

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

Supprimer l'avertissement sur ligne par ligne.

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

supprimez simplement l'avertissement par son nom, puis mettez un commentaire fort à côté en mentionnant la version actuelle de python et numpy, en disant que ce code est fragile et nécessite ces versions et mettez un lien ici. Kick the can en bas de la route.

27
répondu Eric Leschinski 2017-12-11 13:59:02

D'après mon expérience, le même message d'avertissement a été causé par TypeError.

TypeError: invalid type comparison

ainsi, vous pouvez vérifier le type de données du Unnamed: 5

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

Voici comment je peux répliquer le message d'avertissement:

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

j'Espère que ça aide.

1
répondu yhd.leung 2016-11-28 02:20:36

si vos tableaux ne sont pas trop grands ou si vous n'en avez pas trop, vous pourriez vous en tirer en forçant le côté gauche de == pour être une chaîne de caractères:

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

Mais c'est environ 1,5 fois plus lent si df['Unnamed: 5'] est une chaîne, 25-30 fois plus lente si df['Unnamed: 5'] est un petit tableau numpy (Longueur = 10), et 150-160 fois plus lent si c'est un tableau numpy avec une longueur de 100 (Temps en moyenne sur 500 essais).

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)))

Résultat:

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
répondu EL_DON 2018-04-13 16:54:06

une solution rapide est d'utiliser numpy.core.defchararray. J'ai également affronté le même message d'avertissement et j'ai pu le résoudre en utilisant le module ci-dessus.

import numpy.core.defchararray as npd
resultdataset = npd.equal(dataset1, dataset2)
0
répondu Jeet23 2018-06-23 04:37:07

j'obtiens la même erreur quand j'essaie de définir le index_col lecture d'un fichier dans un Panda's de données-image:

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])

je n'ai jamais rencontré une telle erreur précédemment. J'essaye toujours de comprendre la raison derrière ceci (en utilisant l'explication de @Eric Leschinski et d'autres).

quoi qu'il en soit, l'approche suivante résout le problème pour l'instant jusqu'à ce que je trouve la raison:

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

je le mettrai à jour dès que j'aurai trouvé la raison de ce comportement.

0
répondu Dataman 2018-08-20 15:09:34