2012-04-08 17 views
87

我剛剛在我的代碼中發現了一個邏輯錯誤,它導致了各種各樣的問題。我無意中按位AND而不是邏輯AND做了ValueError:具有多個元素的數組的真值是不明確的。使用a.any()或a.all()

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

TO:

我從改變了代碼

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

令我驚訝的是,我得到了非常模糊的錯誤消息:

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

爲什麼類似的錯誤當我使用按位操作時沒有發出 - 我該如何解決這個問題?

+0

什麼爲r的'值[ 「DT」]' – 2012-04-08 13:06:17

+1

熊貓[offer文檔](http://pandas.pydata.org/pandas-docs/stable/indexing.html#boolean-indexing) – Greg 2015-06-09 07:35:23

回答

76

r是一個numpy(rec)數組。所以r["dt"] >= startdate也是一個(布爾型) 數組。對於numpy數組,&操作返回按位數和兩個 布爾數組。

的NumPy的開發者感到沒有通常理解的方式來評估 在布爾上下文的數組:這可能意味着True如果任何元件是 True,或者它可能意味着True如果所有元件是True,或True如果數組的長度不爲零,僅舉出三種可能性。

由於不同的用戶可能有不同的需求和不同的假設,NumPy開發人員拒絕猜測,而是每當試圖在布爾上下文中評估數組時,都會提出ValueError 。將and應用於 兩個numpy數組會導致兩個數組在布爾上下文中進行評估(由 在Python3中調用__bool__或在Python2中調用__nonzero__)。

你的原代碼

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

看起來是正確的。但是,如果您確實想要and,則可以使用(a-b).any()(a-b).all()而不是a and b

+0

你是對的。原始代碼是正確的。該錯誤似乎在代碼中的其他地方。 – 2012-04-08 13:22:02

+0

優秀的解釋。然而,它意味着NumPy效率很低:它完全評估兩個布爾數組,而一個有效的實現會在一個單一循環內評估cond1(i)&& cond2(i),並且除非cond1爲真,否則跳過cond2。 – 2013-08-19 07:18:25

+0

@JoachimWuttke:雖然'np.all'和'np.any'可以短路,但傳遞給它的參數會在'np.all'或'np.any'有機會短路之前評估。爲了做得更好,目前你必須編寫專門的C/Cython代碼[與此類似](http://mail.scipy.org/pipermail/numpy-discussion/2010-October/053579.html)。 – unutbu 2013-08-19 13:22:55

29

我有同樣的問題(即與多條件索引,這裏它找到在某個日期範圍內的數據)。 (a-b).any()(a-b).all()似乎不起作用,至少對我而言。

或者,我發現另一種解決方案,它完美適用於我所需的功能(https://stackoverflow.com/questions/12647471/the-truth-value-of-an-array-with-more-than-one-element-is-ambigous-when-trying-t)。

而不是使用上面的建議的代碼,只需使用numpy.logical_and(a,b)將工作。在這裏,您可能要重寫代碼爲

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

5

的原因的例外是and隱式調用bool。首先在左操作數上(如果左操作數是True),然後在右操作數上。所以x and y相當於bool(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隱含的,而且在ifwhileor ,因此以下任何示例也將失敗:

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

Python中還有更多的函數和語句不要撥打bool來電,例如2 < x < 10只是另一種寫作方式2 < x and x < 10and將撥打boolbool(2 < x) and bool(x < 10)

元素方面等效and將是np.logical_and功能,同樣可以使用np.logical_or等同爲or

對於布爾數組 - 和比較喜歡<<===!=>=>對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的文檔中找到:

相關問題