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 contenant tous les numéros de ligne où la chaîne Peter
est présente dans la colonne Unnamed: 5
.
df = pd.read_Excel(xls_path)
myRows = df[df['Unnamed: 5'] == 'Peter'].index.tolist()
Attention:
"\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)"
Quelle est cette FutureWarning et devrais-je l'ignorer car cela semble fonctionner.
Ce FutureWarning n'est pas de Pandas, mais de numpy et le bogue affecte également matplotlib et d'autres. Voici comment reproduire l'avertissement plus près 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 bogue en utilisant l'opérateur double égal:
import numpy as np
np.arange(5) == np.arange(5).astype(str) #FutureWarning thrown here
Un exemple de Matplotlib affecté par ce FutureWarning dans son implémentation de quiver plot: https://matplotlib.org/examples/pylab_examples/quiver_demo.html
Il y a un désaccord entre Numpy et Python natif sur ce qui devrait se passer lorsque vous comparez une chaîne à des types numériques. Notez que l'opérande de gauche est le turf de python, une chaîne primitive, et que l'opération du milieu est le turf de python, alors que l'opérande de droite est le turf de numpy. Devez-vous renvoyer un scalaire de style Python ou un ndarray de booléens de style Numpy? Numpy dit que ndarray of bool, les développeurs Pythonic ne sont pas d’accord. Impasse classique.
Devrait-il s'agir d'une comparaison élémentaire ou de Scalar si l'élément existe dans le tableau?
Si votre code ou votre bibliothèque utilise les opérateurs in
ou ==
pour comparer une chaîne python à numpy ndarrays, ils ne sont pas compatibles. Par conséquent, si vous l'essayez, il renvoie un scalaire, mais uniquement pour l'instant. L'avertissement indique qu'à l'avenir, ce comportement pourrait changer, de sorte que votre code se répand sur le tapis si python/numpy décide d'adopter le style Numpy.
Numpy et Python sont dans une impasse, pour le moment l'opération renvoie un scalaire, mais peut changer à l'avenir.
https://github.com/numpy/numpy/issues/6784
https://github.com/pandas-dev/pandas/issues/7830
Soit verrouillez votre version de python et numpy et ignorez les avertissements, ou veillez à ce que vos opérandes gauche et droit appartiennent à 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 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é de celui-ci, mentionnant la version actuelle de python et numpy, indiquant que ce code est fragile et nécessite ces versions et place un lien vers cet emplacement. Kick la canette sur la route.
Mon expérience avec le même message d'avertissement a été provoquée par TypeError.
TypeError: comparaison de type non valide
Donc, vous voudrez peut-être 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.
La même erreur se produit lorsque j'essaie de définir le index_col
lisant un fichier dans un cadre de données Panda
:
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 auparavant. J'essaie encore de comprendre la raison derrière cela (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 comprenne 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 mettrai à jour cela dès que je comprendrai la raison d'un tel comportement.
Si vos tableaux ne sont pas trop grands ou si vous n'en avez pas beaucoup, vous pourrez peut-être vous permettre de forcer le côté gauche de ==
à être une chaîne:
myRows = df[str(df['Unnamed: 5']) == 'Peter'].index.tolist()
Mais cela 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 s'il s'agit d'un tableau numpy de longueur 100 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 consiste à utiliser numpy.core.defchararray
. J'ai également été confronté au 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)