FutureWarning ini bukan dari Pandas, ini dari numpy dan bug juga memengaruhi matplotlib dan lainnya, berikut cara mereproduksi peringatan lebih dekat ke sumber masalah:
import numpy as np
print(np.__version__)
'x' in np.arange(5)
FutureWarning: elementwise comparison failed; returning scalar instead, but in the
future will perform elementwise comparison
False
Cara lain untuk mereproduksi bug ini menggunakan operator sama dengan ganda:
import numpy as np
np.arange(5) == np.arange(5).astype(str)
Contoh Matplotlib yang terpengaruh oleh FutureWarning ini di bawah implementasi quiver plot: https://matplotlib.org/examples/pylab_examples/quiver_demo.html
Apa yang terjadi di sini?
Ada ketidaksepakatan antara Numpy dan python asli tentang apa yang harus terjadi ketika Anda membandingkan string dengan tipe numerik numpy. Perhatikan operan kiri adalah turf python, string primitif, dan operasi tengah adalah turf python, tetapi operan kanan adalah turf numpy. Haruskah Anda mengembalikan Scalar gaya Python atau ndarray gaya Numpy dari Boolean? Numpy mengatakan ndarray of bool, pengembang Pythonic tidak setuju. Kebuntuan klasik.
Haruskah itu perbandingan elemen atau Skalar jika item ada dalam array?
Jika kode atau pustaka Anda menggunakan operator in
or ==
untuk membandingkan string python dengan ndarrays numpy, mereka tidak kompatibel, jadi ketika Anda mencobanya, itu mengembalikan skalar, tetapi hanya untuk saat ini. Peringatan menunjukkan bahwa di masa mendatang perilaku ini mungkin berubah sehingga kode Anda akan menyembul ke seluruh karpet jika python / numpy memutuskan untuk mengadopsi gaya Numpy.
Laporan Bug yang dikirim:
Numpy dan Python mengalami kebuntuan, untuk saat ini operasi mengembalikan skalar, tetapi di masa mendatang mungkin berubah.
https://github.com/numpy/numpy/issues/6784
https://github.com/pandas-dev/pandas/issues/7830
Dua solusi solusi:
Anda dapat mengunci versi python dan numpy Anda, mengabaikan peringatan dan mengharapkan perilakunya tidak berubah, atau mengubah operan kiri dan kanan dari ==
dan in
menjadi dari jenis numpy atau jenis numerik python primitif.
Tekan peringatan secara global:
import warnings
import numpy as np
warnings.simplefilter(action='ignore', category=FutureWarning)
print('x' in np.arange(5))
Tekan peringatan baris demi baris.
import warnings
import numpy as np
with warnings.catch_warnings():
warnings.simplefilter(action='ignore', category=FutureWarning)
print('x' in np.arange(2))
print('x' in np.arange(10))
Tekan saja peringatan dengan nama, lalu beri komentar keras di sebelahnya yang menyebutkan versi python dan numpy saat ini, mengatakan kode ini rapuh dan memerlukan versi ini dan letakkan tautan ke sini. Tendang kaleng di jalan.
TLDR: pandas
adalah Jedi; numpy
adalah gubuk; dan python
merupakan kekaisaran galaksi. https://youtu.be/OZczsiCfQQk?t=3
thing
(yang mungkin atau mungkin bukan tipe numpy; saya tidak tahu) dan saya ingin melihat apakahthing == 'some string'
dan mendapatkanbool
hasil yang sederhana , apa yang harus saya lakukan?np.atleast_1d(thing)[0] == 'some string'
? Tapi itu tidak kuat untuk beberapa pelawak yang memasukkan'some string'
elemen pertama dari sebuah array. Saya rasa saya harus menguji jenisnyathing
terlebih dahulu dan kemudian hanya melakukan==
pengujian apakah itu string (atau bukan objek numpy).np.array([1, 2]) == []
akan memunculkan peringatan juga.or babysit your left and right operands to be from a common turf
Saya mendapatkan kesalahan yang sama ketika saya mencoba mengatur
index_col
pembacaan file ke dalamPanda
bingkai data: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])
Saya belum pernah menemui kesalahan seperti itu sebelumnya. Saya masih mencoba mencari tahu alasan di balik ini (menggunakan penjelasan @Eric Leschinski dan lainnya).
Bagaimanapun, pendekatan berikut memecahkan masalah untuk saat ini sampai saya menemukan alasannya:
df = pd.read_csv('my_file.tsv', sep='\t', header=0) ## not setting the index_col df.set_index(['0'], inplace=True)
Saya akan memperbarui ini segera setelah saya mengetahui alasan perilaku tersebut.
sumber
read_csv()
. Bagi saya seperti sesuatu yangpandas
perlu diperbaiki.pd__version__: 0.22.0
;np.__version__: 1.15.4
read_csv
saat menggunakanindex_col
parameter. Saya telah menguji dua penyiapan dengan hasil yang berbeda: 1. numpy versi 1.19.2, Pandas versi 1.1.2: FutureWarning: perbandingan elemen gagal ... 2. numpy versi 1.19.2, Pandas versi 1.1.3: TypeError: ufunc ' isnan 'tidak didukung ...Pengalaman saya terhadap pesan peringatan yang sama disebabkan oleh TypeError.
Jadi, Anda mungkin ingin memeriksa tipe data file
Unnamed: 5
for x in df['Unnamed: 5']: print(type(x)) # are they 'str' ?
Inilah cara saya mereplikasi pesan peringatan:
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
Semoga membantu.
sumber
df['num3'] == '3'
.df.loc[df['num3'] == 3, 'num3'] = 4 # No Error
Bagian ini membantu saya. Terima kasihTidak dapat mengalahkan jawaban Eric Leschinski yang sangat detail, tetapi berikut adalah solusi cepat untuk pertanyaan asli yang menurut saya belum disebutkan - letakkan string dalam daftar dan gunakan
.isin
sebagai ganti==
Sebagai contoh:
import pandas as pd import numpy as np df = pd.DataFrame({"Name": ["Peter", "Joe"], "Number": [1, 2]}) # Raises warning using == to compare different types: df.loc[df["Number"] == "2", "Number"] # No warning using .isin: df.loc[df["Number"].isin(["2"]), "Number"]
sumber
Solusi cepat untuk ini adalah dengan menggunakan
numpy.core.defchararray
. Saya juga menghadapi pesan peringatan yang sama dan dapat menyelesaikannya menggunakan modul di atas.import numpy.core.defchararray as npd resultdataset = npd.equal(dataset1, dataset2)
sumber
Jawaban Eric menjelaskan bahwa masalahnya berasal dari membandingkan Seri Pandas (berisi larik NumPy) dengan string Python. Sayangnya, kedua solusi tersebut hanya menekan peringatan tersebut.
Untuk menulis kode yang tidak menyebabkan peringatan di tempat pertama, bandingkan string Anda secara eksplisit dengan setiap elemen Seri dan dapatkan bool terpisah untuk masing-masing. Misalnya, Anda dapat menggunakan
map
dan fungsi anonim.myRows = df[df['Unnamed: 5'].map( lambda x: x == 'Peter' )].index.tolist()
sumber
Jika array Anda tidak terlalu besar atau Anda tidak memiliki terlalu banyak, Anda mungkin bisa lolos dengan memaksa sisi kiri
==
menjadi string:myRows = df[str(df['Unnamed: 5']) == 'Peter'].index.tolist()
Tapi ini ~ 1,5 kali lebih lambat jika
df['Unnamed: 5']
berupa string, 25-30 kali lebih lambat jikadf['Unnamed: 5']
array numpy kecil (panjang = 10), dan 150-160 kali lebih lambat jika itu adalah array numpy dengan panjang 100 (kali dirata-ratakan selama 500 percobaan) .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)))
Hasil:
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
sumber
==
denganstr
adalah solusi yang baik bagi saya yang hampir tidak mengganggu kinerja pada 1,5 juta baris yang tidak akan menjadi lebih besar dari itu di masa mendatang.Saya mendapat peringatan ini karena saya pikir kolom saya berisi string nol, tetapi saat memeriksa, itu berisi np.nan!
if df['column'] == '':
Mengubah kolom saya menjadi string kosong membantu :)
sumber
Saya telah membandingkan beberapa metode yang mungkin untuk melakukan ini, termasuk panda, beberapa metode numpy, dan metode pemahaman daftar.
Pertama, mari kita mulai dengan garis dasar:
>>> import numpy as np >>> import operator >>> import pandas as pd >>> x = [1, 2, 1, 2] >>> %time count = np.sum(np.equal(1, x)) >>> print("Count {} using numpy equal with ints".format(count)) CPU times: user 52 µs, sys: 0 ns, total: 52 µs Wall time: 56 µs Count 2 using numpy equal with ints
Jadi, dasar kami adalah bahwa hitungannya harus benar
2
, dan kami harus melakukannya50 us
.Sekarang, kami mencoba metode naif:
>>> x = ['s', 'b', 's', 'b'] >>> %time count = np.sum(np.equal('s', x)) >>> print("Count {} using numpy equal".format(count)) CPU times: user 145 µs, sys: 24 µs, total: 169 µs Wall time: 158 µs Count NotImplemented using numpy equal /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/ipykernel_launcher.py:1: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison """Entry point for launching an IPython kernel.
Dan di sini, kami mendapatkan jawaban yang salah (
NotImplemented != 2
), itu membutuhkan waktu lama, dan itu memberi peringatan.Jadi kami akan mencoba metode naif lainnya:
>>> %time count = np.sum(x == 's') >>> print("Count {} using ==".format(count)) CPU times: user 46 µs, sys: 1 µs, total: 47 µs Wall time: 50.1 µs Count 0 using ==
Sekali lagi, jawaban yang salah (
0 != 2
). Ini bahkan lebih berbahaya karena tidak ada peringatan berikutnya (0
dapat disebarkan begitu saja2
).Sekarang, mari kita coba pemahaman daftar:
>>> %time count = np.sum([operator.eq(_x, 's') for _x in x]) >>> print("Count {} using list comprehension".format(count)) CPU times: user 55 µs, sys: 1 µs, total: 56 µs Wall time: 60.3 µs Count 2 using list comprehension
Kami mendapatkan jawaban yang benar di sini, dan ini sangat cepat!
Kemungkinan lain,
pandas
:>>> y = pd.Series(x) >>> %time count = np.sum(y == 's') >>> print("Count {} using pandas ==".format(count)) CPU times: user 453 µs, sys: 31 µs, total: 484 µs Wall time: 463 µs Count 2 using pandas ==
Lambat, tapi benar!
Dan terakhir, opsi yang akan saya gunakan: mentransmisikan
numpy
array keobject
tipe:>>> x = np.array(['s', 'b', 's', 'b']).astype(object) >>> %time count = np.sum(np.equal('s', x)) >>> print("Count {} using numpy equal".format(count)) CPU times: user 50 µs, sys: 1 µs, total: 51 µs Wall time: 55.1 µs Count 2 using numpy equal
Cepat dan tepat!
sumber
'x' in np.arange(5)
, Anda menyarankan untuk melakukan'x' in np.arange(5).astype(object)
(atau serupa :)'x' == np.arange(5).astype(object)
. Baik? IMHO, ini adalah solusi paling elegan yang ditampilkan di sini, jadi saya bingung dengan kurangnya suara positif. Mungkin mengedit jawaban Anda untuk memulai dengan intinya, dan kemudian beralih ke analisis kinerja yang bagus?Saya memiliki kode ini yang menyebabkan kesalahan:
for t in dfObj['time']: if type(t) == str: the_date = dateutil.parser.parse(t) loc_dt_int = int(the_date.timestamp()) dfObj.loc[t == dfObj.time, 'time'] = loc_dt_int
Saya mengubahnya menjadi ini:
for t in dfObj['time']: try: the_date = dateutil.parser.parse(t) loc_dt_int = int(the_date.timestamp()) dfObj.loc[t == dfObj.time, 'time'] = loc_dt_int except Exception as e: print(e) continue
untuk menghindari perbandingan, yaitu melontarkan peringatan - sebagaimana disebutkan di atas. Saya hanya harus menghindari pengecualian karena
dfObj.loc
dalam perulangan for, mungkin ada cara untuk memberitahukannya agar tidak memeriksa baris yang telah diubah.sumber
Dalam kasus saya, peringatan terjadi karena hanya tipe biasa dari pengindeksan boolean - karena rangkaian hanya memiliki np.nan. Demonstrasi (panda 1.0.3):
>>> import pandas as pd >>> import numpy as np >>> pd.Series([np.nan, 'Hi']) == 'Hi' 0 False 1 True >>> pd.Series([np.nan, np.nan]) == 'Hi' ~/anaconda3/envs/ms3/lib/python3.7/site-packages/pandas/core/ops/array_ops.py:255: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison res_values = method(rvalues) 0 False 1 False
Saya pikir dengan pandas 1.0 mereka benar-benar ingin Anda menggunakan
'string'
tipe data baru yang memungkinkanpd.NA
nilai:>>> pd.Series([pd.NA, pd.NA]) == 'Hi' 0 False 1 False >>> pd.Series([np.nan, np.nan], dtype='string') == 'Hi' 0 <NA> 1 <NA> >>> (pd.Series([np.nan, np.nan], dtype='string') == 'Hi').fillna(False) 0 False 1 False
Jangan suka saat mereka mengutak-atik fungsionalitas sehari-hari seperti pengindeksan boolean.
sumber