2010-04-23 38 views
10

我有一個numpy中有兩列的數組。例如:從Python中的NaN(或其他值)的numpy數組中刪除元素對

a = array([[1, 5, nan, 6], 
      [10, 6, 6, nan]]) 
a = transpose(a) 

我想有效地通過兩列迭代中,[:,0]和[:, 1],並刪除滿足某個條件的任何對,在這種情況下,如果它們爲NaN 。我能想到的顯而易見的方式是:

new_a = [] 
for val1, val2 in a: 
    if val2 == nan or val2 == nan: 
    new_a.append([val1, val2]) 

但這似乎很笨重。這是什麼pythonic numpy的方式呢?

謝謝。

回答

29

如果你想只拿不具有NaN的行,這是表達您需要:

>>> import numpy as np 
>>> a[~np.isnan(a).any(1)] 
array([[ 1., 10.], 
     [ 5., 6.]]) 

如果你想不具備的元素,例如中的特定數量的行5:

>>> a[~(a == 5).any(1)] 
array([[ 1., 10.], 
     [ NaN, 6.], 
     [ 6., NaN]]) 

後者顯然是相當於

>>> a[(a != 5).all(1)] 
array([[ 1., 10.], 
     [ NaN, 6.], 
     [ 6., NaN]]) 

說明: 讓我們首先創建例如輸入

>>> import numpy as np 
>>> a = np.array([[1, 5, np.nan, 6], 
...    [10, 6, 6, np.nan]]).transpose() 
>>> a 
array([[ 1., 10.], 
     [ 5., 6.], 
     [ NaN, 6.], 
     [ 6., NaN]]) 

這確定哪些元素是NAN

>>> np.isnan(a) 
array([[False, False], 
     [False, False], 
     [ True, False], 
     [False, True]], dtype=bool) 

這標識哪些行有哪些是真正的任何元素

>>> np.isnan(a).any(1) 
array([False, False, True, True], dtype=bool) 

因爲我們不希望這些,我們否定了最後一個表達式:

>>> ~np.isnan(a).any(1) 
array([ True, True, False, False], dtype=bool) 

最後,我們使用布爾陣列選擇我們想要的行:

>>> a[~np.isnan(a).any(1)] 
array([[ 1., 10.], 
     [ 5., 6.]]) 
+2

+1:超清晰且有幫助的解釋,我喜歡〜np.isnan,因爲它可以說明你在做什麼。 – tom10 2010-04-23 18:20:14

+0

多麼可怕的答案 – Tjorriemorrie 2014-11-14 15:25:33

2

我認爲list comprehensions應該這樣做。例如,

new_a = [(val1, val2) for (val1, val2) in a if math.isnan(val1) or math.isnan(val2)] 
+2

因爲'nan == nan'返回false,所以您實際上需要使測試類似'val1!= val1'。但+1。 – 2010-04-23 01:03:00

+0

我編輯了上面的內容...老實說,我從來不需要'NaN',所以我主要是在編寫列表的形式。基於這裏的文檔:http://docs.python.org/library/math.html#math.isnan,我認爲這應該工作... – ig0774 2010-04-23 01:08:41

+2

不應該是: ...在一個地方不是數學isnan(val1)而不是math.isnan(val2)? – user248237dfsf 2010-04-23 01:22:20

3

您可以在陣列轉換爲masked array,並使用compress_rows method

import numpy as np 
a = np.array([[1, 5, np.nan, 6], 
      [10, 6, 6, np.nan]]) 
a = np.transpose(a) 
print(a) 
# [[ 1. 10.] 
# [ 5. 6.] 
# [ NaN 6.] 
# [ 6. NaN]] 
b=np.ma.compress_rows(np.ma.fix_invalid(a)) 
print(b) 
# [[ 1. 10.] 
# [ 5. 6.]] 
+2

+1:哇!我經常看不到使用和建議的蒙版陣列!好的! – EOL 2010-04-23 09:19:56

3

不從ig0774的答案,這是完全有效的,符合Python實際上是在正常的方式減損用純Python做這些事情,但是:numpy支持一個布爾索引系統,它也可以完成這項工作。

new_a = a[(a==a).all(1)] 

我不確定副手哪種方法更有效(或更快執行)。

如果您想要使用不同的條件來選擇行,這將不得不被改變,並且具體取決於條件。如果它的東西,可以爲每個數組元素單獨進行評估,你可以只用合適的測試更換a==a,例如消除與大於100號碼都行,你可以做

new_a = a[(a<=100).all(1)] 

但如果你是試圖做一些涉及連續所有元素的事情(比如排除總和超過100的所有行),這可能會更復雜。如果是這種情況,我可以嘗試編輯更具體的答案,如果你想分享你的確切條件。

+0

+1:用於矢量化方法。這幾乎總是更快,是使用numpy的主要原因之一。 – tom10 2010-04-23 04:44:32

相關問題