ValueError: Giá trị thật của một mảng có nhiều hơn một phần tử là không rõ ràng. Sử dụng a.any () hoặc a.all ()


221

Tôi vừa phát hiện ra một lỗi logic trong mã của mình, nó gây ra đủ loại vấn đề. Tôi đã vô tình làm một chút thay vì một logic VÀ .

Tôi đã thay đổi mã từ:

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

ĐẾN:

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

Thật ngạc nhiên, tôi nhận được thông báo lỗi khá khó hiểu:

ValueError: Giá trị thật của một mảng có nhiều hơn một phần tử là không rõ ràng. Sử dụng a.any () hoặc a.all ()

Tại sao một lỗi tương tự không được phát ra khi tôi sử dụng thao tác bitwise - và làm cách nào để khắc phục lỗi này?


1
Pandas cũng cung cấp tài liệu cho việc này
Greg

Câu trả lời:


164

rlà một mảng numpy (rec). Vì vậy, r["dt"] >= startdatecũng là một mảng (boolean). Đối với mảng numpy, &hoạt động trả về phần tử - và của hai mảng boolean.

Các nhà phát triển NumPy cảm thấy không có cách nào thông thường để đánh giá một mảng trong ngữ cảnh boolean: nó có thể có nghĩa là Truenếu có bất kỳ phần tử nàoTrue , hoặc có thể có nghĩa là Truenếu tất cả các phần tử là True, hoặc Truenếu mảng có độ dài khác không, chỉ cần đặt tên ba khả năng.

Do những người dùng khác nhau có thể có nhu cầu khác nhau và các giả định khác nhau, nên các nhà phát triển NumPy đã từ chối đoán và thay vào đó quyết định tăng ValueError mỗi khi người ta cố gắng đánh giá một mảng trong bối cảnh boolean. Áp dụng andcho hai mảng numpy làm cho hai mảng được đánh giá trong bối cảnh boolean (bằng cách gọi __bool__trong Python3 hoặc __nonzero__trong Python2).

Mã ban đầu của bạn

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

có vẻ đúng Tuy nhiên, nếu bạn muốn and, sau đó thay vì a and bsử dụng (a-b).any()hoặc (a-b).all().


2
Bạn đúng. Mã ban đầu là chính xác. Các lỗi dường như nằm ở một nơi khác trong mã.
Homunculus Reticulli

2
Giải thích tuyệt vời. Tuy nhiên, điều đó ngụ ý rằng NumPy khá kém hiệu quả: nó đánh giá đầy đủ cả hai mảng boolean, trong khi đó việc triển khai hiệu quả sẽ đánh giá cond1 (i) && cond2 (i) trong một vòng lặp duy nhất và bỏ qua cond2 trừ khi cond1 là đúng.
Joachim W

@JoachimWuttke: Mặc dù np.allnp.anycó khả năng ngắn mạch, nhưng đối số được truyền cho nó được đánh giá trước np.allhoặc np.anycó cơ hội ngắn mạch. Để làm tốt hơn, hiện tại, bạn phải viết mã C / Cython chuyên dụng tương tự như thế này .
unutbu

47

Tôi gặp vấn đề tương tự (tức là lập chỉ mục với nhiều điều kiện, ở đây là tìm dữ liệu trong một phạm vi ngày nhất định). Các (a-b).any()hoặc (a-b).all()dường như không làm việc, ít nhất là đối với tôi.

Ngoài ra, tôi đã tìm thấy một giải pháp khác hoạt động hoàn hảo cho chức năng mong muốn của mình ( Giá trị thật của một mảng có nhiều hơn một phần tử là mơ hồ khi cố gắng lập chỉ mục một mảng ).

Thay vì sử dụng mã được đề xuất ở trên, chỉ cần sử dụng một numpy.logical_and(a,b)sẽ làm việc. Ở đây bạn có thể muốn viết lại mã như

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

34

Lý do cho ngoại lệ là andcác cuộc gọi ngầm bool. Đầu tiên trên toán hạng bên trái và (nếu toán hạng bên trái là True) sau đó trên toán hạng bên phải. Như vậy x and ylà tương đương vớibool(x) and bool(y) .

Tuy nhiên, booltrên một numpy.ndarray(nếu nó chứa nhiều hơn một phần tử) sẽ đưa ra ngoại lệ bạn đã thấy:

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

Các bool()cuộc gọi là trong tiềm ẩn and, mà còn trong if, while, or, vì vậy bất kỳ trong những ví dụ sau đây cũng sẽ thất bại:

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

Có nhiều hàm và câu lệnh trong Python ẩn boolcác cuộc gọi, ví dụ 2 < x < 10chỉ là một cách viết khác 2 < x and x < 10. Và ý andchí sẽ gọi bool: bool(2 < x) and bool(x < 10).

Các yếu tố khôn ngoan tương đương cho andsẽ là np.logical_andchức năng, tương tự bạn có thể sử dụng np.logical_ornhư tương đương cho or.

Đối với mảng boolean - và so sánh thích <, <=, ==, !=, >=>trên NumPy mảng trở lại mảng NumPy boolean - bạn cũng có thể sử dụng các yếu tố khôn ngoan Bitwise chức năng (và các nhà khai thác): np.bitwise_and( &nhà điều hành)

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

bitwise_or( |nhà điều hành):

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

Một danh sách đầy đủ các hàm logic và nhị phân có thể được tìm thấy trong tài liệu NumPy:


2

nếu bạn làm việc với pandasnhững gì đã giải quyết vấn đề cho tôi là tôi đã cố gắng tính toán khi tôi có các giá trị NA, thì giải pháp là chạy:

df = df.dropna()

Và sau đó tính toán mà thất bại.


0

Thông báo lỗi được gõ này cũng hiển thị trong khi việc if-statementso sánh được thực hiện khi có một mảng và ví dụ là bool hoặc int. Xem ví dụ:

... code snippet ...

if dataset == bool:
    ....

... code snippet ...

Mệnh đề này có tập dữ liệu dưới dạng mảng và bool là "cửa mở" ... Truehoặc False.

Trong trường hợp chức năng được gói trong một try-statementbạn sẽ nhận được except Exception as error:thông báo mà không có loại lỗi:

Giá trị thật của một mảng có nhiều hơn một phần tử là mơ hồ. Sử dụng a.any () hoặc a.all ()


-6

hãy thử điều này => numpy.array (r) hoặc numpy.array (yourvariable) theo sau là lệnh để so sánh bất cứ điều gì bạn muốn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.