ValueError: Nilai kebenaran sebuah array dengan lebih dari satu elemen bersifat ambigu. Gunakan a.any () atau a.all ()


221

Saya baru saja menemukan bug logis dalam kode saya yang menyebabkan segala macam masalah. Saya secara tidak sengaja melakukan bitwise DAN bukannya logika AND .

Saya mengubah kode dari:

r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]

UNTUK:

r = mlab.csv2rec(datafile, delimiter=',', names=COL_HEADERS)
mask = ((r["dt"] >= startdate) and (r["dt"] <= enddate))
selected = r[mask]

Yang mengejutkan saya, saya mendapat pesan kesalahan yang agak samar:

ValueError: Nilai kebenaran sebuah array dengan lebih dari satu elemen bersifat ambigu. Gunakan a.any () atau a.all ()

Mengapa kesalahan serupa tidak dipancarkan ketika saya menggunakan operasi bitwise - dan bagaimana cara memperbaikinya?


1
Pandas menawarkan dokumentasi untuk hal ini juga
Greg

Jawaban:


164

radalah array numpy (rec). Begitu r["dt"] >= startdatejuga array (boolean). Untuk array numpy, &operasi mengembalikan elemen-dan dari dua array boolean.

Pengembang NumPy merasa tidak ada satu pun cara yang dipahami untuk mengevaluasi sebuah array dalam konteks boolean: itu bisa berarti Truejika ada elemen True, atau bisa berarti Truejika semua elemen True, atau Truejika array memiliki panjang tidak nol, hanya untuk menyebutkan tiga kemungkinan.

Karena pengguna yang berbeda mungkin memiliki kebutuhan dan asumsi yang berbeda, pengembang NumPy menolak untuk menebak dan sebaliknya memutuskan untuk meningkatkan ValueError setiap kali seseorang mencoba untuk mengevaluasi array dalam konteks boolean. Menerapkan andke dua array numpy menyebabkan dua array dievaluasi dalam konteks boolean (dengan memanggil __bool__Python3 atau __nonzero__Python2).

Kode asli Anda

mask = ((r["dt"] >= startdate) & (r["dt"] <= enddate))
selected = r[mask]

terlihat benar. Namun, jika Anda memang menginginkannya and, maka alih-alih a and bgunakan (a-b).any()atau (a-b).all().


2
Kamu benar. Kode aslinya benar. Bug tersebut tampaknya terletak di tempat lain dalam kode.
Homunculus Reticulli

2
Penjelasan yang bagus. Ini menyiratkan, bagaimanapun, bahwa NumPy cukup tidak efisien: ia sepenuhnya mengevaluasi kedua array boolean, sedangkan implementasi yang efisien akan mengevaluasi cond1 (i) && cond2 (i) di dalam satu loop tunggal, dan melewati cond2 kecuali cond1 benar.
Joachim W

@ JoachimWuttke: Meskipun np.alldan np.anymampu melakukan hubungan arus pendek, argumen yang diteruskan kepadanya dievaluasi sebelum np.allatau np.anymemiliki peluang untuk mengalami hubungan arus pendek. Untuk melakukan yang lebih baik, saat ini, Anda harus menulis kode C / Cython khusus yang mirip dengan ini .
unutbu

47

Saya memiliki masalah yang sama (yaitu pengindeksan dengan berbagai kondisi, di sini menemukan data dalam rentang tanggal tertentu). The (a-b).any()atau (a-b).all()tampak tidak bekerja, setidaknya untuk saya.

Atau saya menemukan solusi lain yang berfungsi sempurna untuk fungsionalitas yang saya inginkan ( Nilai kebenaran sebuah array dengan lebih dari satu elemen ambigu ketika mencoba mengindeks sebuah array ).

Alih-alih menggunakan kode yang disarankan di atas, cukup menggunakan numpy.logical_and(a,b)akan bekerja. Di sini Anda mungkin ingin menulis ulang kode sebagai

selected  = r[numpy.logical_and(r["dt"] >= startdate, r["dt"] <= enddate)]

34

Alasan pengecualian adalah bahwa andpanggilan secara implisit bool. Pertama di operan kiri dan (jika operan kiri True) maka di operan kanan. Jadi x and ysetara dengan bool(x) and bool(y).

Namun boolpada a numpy.ndarray(jika mengandung lebih dari satu elemen) akan mengeluarkan pengecualian yang telah Anda lihat:

>>> import numpy as np
>>> arr = np.array([1, 2, 3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The bool()panggilan yang implisit and, tetapi juga dalam if, while, or, sehingga salah satu contoh berikut akan juga gagal:

>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> if arr: pass
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> while arr: pass
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

>>> arr or arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Ada lebih banyak fungsi dan pernyataan dalam Python yang menyembunyikan boolpanggilan, misalnya 2 < x < 10hanyalah cara penulisan lainnya 2 < x and x < 10. Dan andakan memanggil bool: bool(2 < x) and bool(x < 10).

The elemen-bijaksana setara untuk andakan menjadi np.logical_andfungsi, sama Anda bisa menggunakan np.logical_orsebagai setara untuk or.

Untuk array boolean - dan perbandingan suka <, <=, ==, !=, >=dan >pada NumPy array kembali array NumPy boolean - Anda juga dapat menggunakan elemen-bijaksana bitwise fungsi (dan operator): np.bitwise_and( &operator)

>>> np.logical_and(arr > 1, arr < 3)
array([False,  True, False], dtype=bool)

>>> np.bitwise_and(arr > 1, arr < 3)
array([False,  True, False], dtype=bool)

>>> (arr > 1) & (arr < 3)
array([False,  True, False], dtype=bool)

dan bitwise_or( |operator):

>>> np.logical_or(arr <= 1, arr >= 3)
array([ True, False,  True], dtype=bool)

>>> np.bitwise_or(arr <= 1, arr >= 3)
array([ True, False,  True], dtype=bool)

>>> (arr <= 1) | (arr >= 3)
array([ True, False,  True], dtype=bool)

Daftar lengkap fungsi logis dan biner dapat ditemukan di dokumentasi NumPy:


2

jika Anda bekerja dengan pandasapa yang memecahkan masalah bagi saya adalah bahwa saya mencoba melakukan perhitungan ketika saya memiliki nilai NA, solusinya adalah menjalankan:

df = df.dropna()

Dan setelah itu perhitungan itu gagal.


0

Pesan kesalahan yang diketik ini juga menunjukkan sementara if-statementperbandingan dilakukan di mana ada array dan misalnya bool atau int. Lihat misalnya:

... code snippet ...

if dataset == bool:
    ....

... code snippet ...

Klausa ini memiliki dataset sebagai array dan bool adalah "pintu terbuka" ... Trueatau False.

Dalam hal fungsi dibungkus dalam try-statementAnda akan menerima except Exception as error:pesan tanpa jenis kesalahan:

Nilai sebenarnya dari sebuah array dengan lebih dari satu elemen adalah ambigu. Gunakan a.any () atau a.all ()


-6

coba ini => numpy.array (r) atau numpy.array (yourvariable) diikuti oleh perintah untuk membandingkan apa pun yang Anda inginkan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.