ValueError: ค่าความจริงของอาร์เรย์ที่มีองค์ประกอบมากกว่าหนึ่งรายการนั้นไม่ชัดเจน ใช้ a.any () หรือ a.all ()


221

ฉันเพิ่งค้นพบข้อผิดพลาดเชิงตรรกะในรหัสของฉันซึ่งก่อให้เกิดปัญหาทุกประเภท ผมก็ไม่ได้ตั้งใจทำบิตและแทนที่จะเป็นตรรกะและ

ฉันเปลี่ยนรหัสจาก:

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

ถึง:

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

ด้วยความประหลาดใจของฉันฉันได้รับข้อความแสดงข้อผิดพลาดที่ค่อนข้างลึกลับ:

ValueError: ค่าความจริงของอาร์เรย์ที่มีองค์ประกอบมากกว่าหนึ่งรายการนั้นไม่ชัดเจน ใช้ a.any () หรือ a.all ()

ทำไมข้อผิดพลาดที่คล้ายกันไม่ถูกปล่อยออกมาเมื่อฉันใช้การดำเนินการระดับบิต - และฉันจะแก้ไขได้อย่างไร


1
Pandas เสนอเอกสารสำหรับสิ่งนี้ด้วย
Greg

คำตอบ:


164

rเป็นอาร์เรย์ numpy (rec) ดังนั้นr["dt"] >= startdateยังเป็นอาร์เรย์ (บูลีน) สำหรับอาร์เรย์ numpy การ&ดำเนินการส่งคืน elementwise- และอาร์เรย์บูลีนสองชุด

นักพัฒนา NumPy รู้สึกว่าไม่มีใครที่เข้าใจกันทั่วไปวิธีในการประเมินอาร์เรย์ในบริบทแบบบูลที่ใช้งาน: มันอาจหมายถึงTrueถ้าใด ๆองค์ประกอบ TrueหรือมันอาจหมายถึงTrueถ้าทุกองค์ประกอบTrueหรือTrueถ้าอาร์เรย์มีไม่ใช่ศูนย์ความยาวเพียงเพื่อชื่อสาม ความเป็นไปได้

เนื่องจากผู้ใช้ที่แตกต่างกันอาจมีความต้องการที่แตกต่างกันและมีสมมติฐานที่แตกต่างกันนักพัฒนา NumPy ปฏิเสธที่จะคาดเดาและตัดสินใจที่จะเพิ่ม ValueError แทนเมื่อใดก็ตามที่ผู้ใช้พยายามประเมินอาร์เรย์ในบริบทบูลีน การนำandไปใช้กับสอง numpy arrays ทำให้ทั้งสองอาร์เรย์ได้รับการประเมินในบริบทบูลีน (โดยการเรียกใช้__bool__ใน Python3 หรือ__nonzero__Python2)

รหัสเดิมของคุณ

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

ดูถูกต้อง แต่ถ้าคุณไม่ต้องการandแล้วแทนการa and bใช้หรือ(a-b).any()(a-b).all()


2
คุณถูก. รหัสเดิมถูกต้อง ข้อผิดพลาดดูเหมือนจะอยู่ที่อื่นในรหัส
Homunculus Reticulli

2
คำอธิบายที่ยอดเยี่ยม อย่างไรก็ตามมันบอกเป็นนัยว่า NumPy ค่อนข้างไม่มีประสิทธิภาพ: ประเมินทั้งอาร์เรย์บูลีนอย่างเต็มที่ในขณะที่การใช้งานที่มีประสิทธิภาพจะประเมิน cond1 (i) && cond2 (i) ภายในวงเดียวและข้าม cond2 เว้นแต่ cond1 จะเป็นจริง
Joachim W

@JoachimWuttke: ถึงแม้ว่าnp.allและnp.anyมีความสามารถในการลัดวงจรอาร์กิวเมนต์ที่ส่งไปยังมันจะถูกประเมินก่อนnp.allหรือnp.anyมีโอกาสลัดวงจร จะทำดีกว่าปัจจุบันที่คุณจะต้องเขียนเฉพาะรหัส C / Cython ที่คล้ายกันนี้
unutbu

47

ฉันมีปัญหาเดียวกัน (เช่นการจัดทำดัชนีที่มีหลายเงื่อนไขนี่คือการค้นหาข้อมูลในช่วงวันที่ที่แน่นอน) (a-b).any()หรือ(a-b).all()ดูเหมือนไม่ได้ทำงานอย่างน้อยสำหรับฉัน

อีกทางหนึ่งฉันพบวิธีแก้ไขปัญหาอื่นที่ทำงานได้อย่างสมบูรณ์แบบสำหรับฟังก์ชั่นที่ฉันต้องการ ( ค่าความจริงของอาร์เรย์ที่มีองค์ประกอบมากกว่าหนึ่งองค์ประกอบนั้นน่าสงสัยเมื่อพยายามทำดัชนีอาร์เรย์ )

แทนที่จะใช้รหัสที่แนะนำด้านบนเพียงแค่ใช้numpy.logical_and(a,b)งาน ที่นี่คุณอาจต้องการเขียนรหัสใหม่เป็น

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

34

เหตุผลสำหรับข้อยกเว้นคือว่าสายโดยปริยายand boolครั้งแรกในตัวถูกดำเนินการด้านซ้ายและ (ถ้าตัวถูกดำเนินการด้านซ้ายเป็นTrue) จากนั้นในตัวถูกดำเนินการด้านขวา ดังนั้นจะเทียบเท่ากับx and ybool(x) and bool(y)

อย่างไรก็ตามboolในnumpy.ndarray(ถ้ามันมีมากกว่าหนึ่งองค์ประกอบ) จะโยนข้อยกเว้นที่คุณได้เห็น:

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

bool()โทรอยู่ในนัยandแต่ยังอยู่ในif, while, orเพื่อให้การใด ๆ ของตัวอย่างต่อไปนี้ก็จะล้มเหลว

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

มีฟังก์ชั่นอื่น ๆ อีกมากมายและงบในหลามที่ซ่อนboolสายเช่นเป็นเพียงวิธีการเขียนอีก2 < x < 10 2 < x and x < 10และandจะโทร:boolbool(2 < x) and bool(x < 10)

องค์ประกอบฉลาดเทียบเท่าandจะเป็นnp.logical_andฟังก์ชั่นในทำนองเดียวกันคุณสามารถใช้เป็นเทียบเท่าnp.logical_oror

สำหรับอาร์เรย์แบบบูล - และการเปรียบเทียบชอบ<, <=, ==, !=, >=และ>บนอาร์เรย์ NumPy กลับอาร์เรย์ NumPy บูล - คุณยังสามารถใช้องค์ประกอบที่ชาญฉลาดบิตฟังก์ชั่น (และผู้ประกอบการ): np.bitwise_and( &ผู้ดำเนินการ)

>>> 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( |ผู้ประกอบการ):

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

รายการฟังก์ชันตรรกะและไบนารีที่สมบูรณ์สามารถพบได้ในเอกสาร NumPy:


2

ถ้าคุณทำงานกับpandasสิ่งที่แก้ไขปัญหาสำหรับฉันก็คือฉันพยายามคำนวณเมื่อฉันมีค่า NA วิธีแก้ปัญหาก็คือ:

df = df.dropna()

และหลังจากนั้นการคำนวณที่ล้มเหลว


0

ข้อความแสดงข้อผิดพลาดนี้ยังแสดงให้เห็นในขณะที่การif-statementเปรียบเทียบเสร็จสิ้นเมื่อมีอาร์เรย์และตัวอย่างเช่นบูลหรือ int ดูตัวอย่าง:

... code snippet ...

if dataset == bool:
    ....

... code snippet ...

ข้อนี้มีชุดข้อมูลที่เป็นอาร์เรย์และบูลเป็น euhm "เปิดประตู" ... หรือTrueFalse

ในกรณีที่ฟังก์ชั่นถูกห่อหุ้มภายในtry-statementคุณจะได้รับexcept Exception as error:ข้อความโดยไม่มีข้อผิดพลาด:

ค่าความจริงของอาร์เรย์ที่มีองค์ประกอบมากกว่าหนึ่งองค์ประกอบนั้นไม่ชัดเจน ใช้ a.any () หรือ a.all ()


-6

ลองใช้ => numpy.array (r) หรือ numpy.array (yourvariable) ตามด้วยคำสั่งเพื่อเปรียบเทียบสิ่งที่คุณต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.