it-swarm.com.ru

FutureWarning: поэлементное сравнение не удалось; возвращаем скаляр, но в дальнейшем будем выполнять поэлементное сравнение

Я использую Pandas 0.19.1 на Python 3. Я получаю предупреждение об этих строках кода. Я пытаюсь получить список, который содержит все номера строк, где строка Peter присутствует в столбце Unnamed: 5.

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

Предупреждение:

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

Что это за FutureWarning и я должен игнорировать его, так как он, кажется, работает. 

26
Arturo

Это предупреждение о будущем не от Pandas, а от numpy, и ошибка также влияет на matplotlib и других, вот как воспроизвести предупреждение ближе к источнику проблемы:

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

Еще один способ воспроизвести эту ошибку, используя оператор двойного равенства:

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

Пример Matplotlib, затронутого этим FutureWarning при реализации их колчана: https://matplotlib.org/examples/pylab_examples/quiver_demo.html

Что тут происходит?

Существует разногласие между Numpy и нативным Python относительно того, что должно произойти, когда вы сравниваете строки с числовыми типами Numpy. Обратите внимание, что левый операнд - это дерновина питона, примитивная строка, а средняя операция - это дерна питона, но правый операнд - это дерновина numpy. Стоит ли возвращать Scalar в стиле Python или ndarray в стиле Numpy? Numpy говорит ndarray о bool, Pythonic разработчики не согласны. Классическое противостояние.

Должно ли это быть поэлементное сравнение или Скалярное, если элемент существует в массиве? 

Если ваш код или библиотека используют операторы in или == для сравнения строки python с numy ndarrays, они несовместимы, поэтому, если вы попробуете это, он вернет скаляр, но только сейчас. Предупреждение указывает на то, что в будущем это поведение может измениться, поэтому ваш код терзает весь ковер, если python/numpy решит принять стиль Numpy. 

Представленные отчеты об ошибках:

Numpy и Python находятся в противостоянии, на данный момент операция возвращает скаляр, но в будущем она может измениться.

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

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

Два обходных решения:

Либо заблокируйте вашу версию Python и NumPy и игнорировать предупреждения, либо присматривайте за левым и правым операндами из общего поля.

Подавить предупреждение глобально:

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

Подавить предупреждение построчно.

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

Просто подавьте предупреждение по имени, затем поместите громкий комментарий рядом с ним, в котором упоминается текущая версия python и numpy, говоря, что этот код хрупкий и требует этих версий, и поместите ссылку здесь. Пните банку вниз по дороге.

39
Eric Leschinski

Мой опыт с тем же предупреждением был вызван TypeError.

Ошибка типа: недопустимое сравнение типов

Итак, вы можете проверить тип данных Unnamed: 5

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

Вот как я могу повторить предупреждение: 

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

Надеюсь, поможет.

1
yhd.leung

Я получаю ту же ошибку при попытке установить index_col для чтения файла в фрейм данных 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])

Я никогда не сталкивался с такой ошибкой ранее. Я все еще пытаюсь выяснить причину этого (используя объяснение @Eric Leschinski и другие).

Во всяком случае, следующий подход решает проблему, пока я не выясню причину:

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

Я обновлю это, как только выясню причину такого поведения. 

1
Dataman

Если ваши массивы не слишком велики или у вас их не слишком много, вам, возможно, удастся скомпилировать левую часть == в строку:

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

Но это примерно в 1,5 раза медленнее, если df['Unnamed: 5'] - строка, в 25-30 раз медленнее, если df['Unnamed: 5'] - маленький массив с нулевыми значениями (длина = 10), и в 150-160 раз медленнее, если это массивный массив с длиной 100 (в среднем более 500 раз) испытания).

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

Результат:

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

Быстрый обходной путь для этого заключается в использовании numpy.core.defchararray. Я также столкнулся с тем же предупреждающим сообщением и смог решить его, используя вышеуказанный модуль.

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