FutureWarning: la comparación de elementwise falló; volver escalar, pero en el futuro se realizará la comparación elementwise

Estoy usando Pandas 0.19.1 en Python 3. Recibo una advertencia en estas líneas de código. Estoy intentando obtener una lista que contenga todos los números de fila donde la cadena Peter está presente en la columna Unnamed: 5 .

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

Advertencia:

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

¿Qué es este FutureWarning y debería ignorarlo ya que parece funcionar?

Este FutureWarning no es de Pandas, es de numpy y el error también afecta a matplotlib y otros, aquí está cómo reproducir la advertencia más cercana a la fuente del problema:

 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 

Otra forma de reproducir este error usando el operador doble es igual a:

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

Un ejemplo de Matplotlib afectado por este FutureWarning en su implementación de la ttwig de carcaj: https://matplotlib.org/examples/pylab_examples/quiver_demo.html

¿Que está pasando aqui?

Hay un desacuerdo entre Numpy y python nativo sobre lo que debería suceder cuando se comparan las cadenas con los tipos numéricos de numpy. Observe que el operando izquierdo es el césped de python, una cadena primitiva, y la operación del medio es el césped de python, pero el operando de la derecha es el césped de numpy. ¿Debería devolver un escalar de estilo Python o un ndarray de estilo Numpy de booleano? Numpy dice que ndarray de bool, los desarrolladores de Pythonic no están de acuerdo. Enfrentamiento clásico.

¿Debería ser una comparación elemental o escalar si el elemento existe en la matriz?

Si su código o biblioteca utiliza los operadores in o == para comparar la cadena de python con las ndarrays numpy, no son compatibles, de modo que si lo prueba, devuelve un escalar, pero solo por ahora. La Advertencia indica que, en el futuro, este comportamiento podría cambiar, por lo que su código se propagará por toda la alfombra si Python / numpy deciden adoptar el estilo Numpy.

Informes de errores enviados:

Numpy y Python están en un punto muerto, por ahora la operación devuelve un escalar, pero en el futuro puede cambiar.

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

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

Dos soluciones alternativas:

Bloquee su versión de python y numpy e ignore las advertencias, o cuide a sus operandos izquierdo y derecho para que sean de un territorio común.

Suprimir la advertencia globalmente:

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

Suprimir la advertencia línea por línea.

 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 

Simplemente suprima la advertencia por su nombre, luego coloque un fuerte comentario junto a ella mencionando la versión actual de python y numpy, diciendo que este código es frágil y requiere estas versiones y ponga un enlace aquí. Patea la lata por el camino.

Mi experiencia con el mismo mensaje de advertencia fue causada por TypeError.

TypeError: comparación de tipo no válido

Por lo tanto, es posible que desee comprobar el tipo de datos del Unnamed: 5

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

Aquí es cómo puedo replicar el mensaje de advertencia:

 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 

Espero eso ayude.

Una solución rápida para esto es usar numpy.core.defchararray . También me enfrenté al mismo mensaje de advertencia y pude resolverlo usando el módulo anterior.

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

Recibo el mismo error cuando bash configurar el index_col leyendo un archivo en el dataframe de 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]) 

Nunca he encontrado tal error anteriormente. Todavía estoy tratando de averiguar la razón detrás de esto (utilizando la explicación de @Eric Leschinski y otras).

De todos modos, el siguiente enfoque resuelve el problema por ahora hasta que descubra la razón:

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

Actualizaré esto tan pronto como descubra la razón de tal comportamiento.

Si sus arreglos no son demasiado grandes o si no tiene muchos de ellos, es posible que pueda escapar forzando el lado izquierdo de == para que sea una cadena:

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

Pero esto es ~ 1.5 veces más lento si df['Unnamed: 5'] es una cadena, 25-30 veces más lento si df['Unnamed: 5'] es una matriz numpy pequeña (longitud = 10), y 150-160 veces más lento si es una matriz numpy con una longitud de 100 (promedios de más de 500 bashs).

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

Resultado:

 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