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