2016-08-13 90 views
0

當使用自定義類的numpy的array喜歡的工作:如何在numpy類的數組上使用掩碼索引?

class TestClass: 
    active = False 

如何使用內聯屏蔽(布爾數組索引)喜歡這裏描述:http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays

直接嘗試失敗:

items = np.array([TestClass() for _ in range(10)]) 
items[items.active] 

    AttributeError: 'numpy.ndarray' object has no attribute 'active' 

有什麼建議麼?

回答

2

所以你的陣列dtype=object(打印),每個元素指向您的類的實例:

items = np.array([TestClass() for _ in range(10)]) 

現在試試:

items.active 

items是一個數組; active是你的類的屬性,而不是你的對象數組的屬性。您的定義不會爲類ndarray添加任何功能。錯誤不在掩飾中;它試圖獲取實例屬性。

像這樣的數組上的許多操作都是迭代完成的。這種數組類似於普通的Python列表。

[obj.active for obj in items] 

或把它放回一個數組

np.array([obj...]) 

items[[True,False,True,...]]應該工作,但是這是因爲面膜是一個布爾值列表或數組了。

====================

讓修改您的類,以便它顯示了一些有趣的事情。請注意,我分配active到實例,而不是,像你一樣,對類:

In [1671]: class TestClass: 
     ...:  def __init__(self,val): 
     ...:  self.active = bool(val%2) 

In [1672]: items = np.array([TestClass(i) for i in range(10)]) 

In [1674]: items 
Out[1674]: 
array([<__main__.TestClass object at 0xb106758c>, 
     <__main__.TestClass object at 0xb117764c>, 
     ... 
     <__main__.TestClass object at 0xb269850c>], dtype=object) 
# print of the array isn't interesting. The class needs a `__str__` method. 

這種簡單的迭代訪問屬性:

In [1675]: [i.active for i in items] 
Out[1675]: [False, True, False, True, False, True, False, True, False, True] 

np.frompyfunc提供了訪問每個元素的一個更強大的方式的數組。 operator.attrgetter('active')(i)是做i.active的功能性方法。

In [1676]: f=np.frompyfunc(operator.attrgetter('active'),1,1) 
In [1677]: f(items) 
Out[1677]: array([False, True, False, True, False, True, False, True, False, True], dtype=object) 

但是當我改變陣列的形狀出現這一功能的主要優點:

In [1678]: f(items.reshape(2,5)) 
Out[1678]: 
array([[False, True, False, True, False], 
     [True, False, True, False, True]], dtype=object) 

注意這個陣列是D型對象。這就是frompyfunc所做的。爲了獲得boolean數組,我們需要改變類型:

In [1679]: f(items.reshape(2,5)).astype(bool) 
Out[1679]: 
array([[False, True, False, True, False], 
     [ True, False, True, False, True]], dtype=bool) 

np.vectorize使用frompyfunc,並使得D型多一點人性化。但是在時機上它有點慢。

===============

擴大喬恩的評論

In [1702]: class TestClass: 
     ...:  def __init__(self,val): 
     ...:  self.active = bool(val%2) 
     ...:  def __bool__(self): 
     ...:   return self.active 
     ...:  def __str__(self): 
     ...:   return 'TestClass(%s)'%self.active 
     ...:  def __repr__(self): 
     ...:   return str(self) 

In [1707]: items = np.array([TestClass(i) for i in range(5)]) 

items現在以翔實的方式顯示;並轉換爲字符串:

In [1708]: items 
Out[1708]: 
array([TestClass(False), TestClass(True), TestClass(False), 
     TestClass(True), TestClass(False)], dtype=object) 
In [1709]: items.astype('S20') 
Out[1709]: 
array([b'TestClass(False)', b'TestClass(True)', b'TestClass(False)', 
     b'TestClass(True)', b'TestClass(False)'], 
     dtype='|S20') 

,並轉換爲bool

In [1710]: items.astype(bool) 
Out[1710]: array([False, True, False, True, False], dtype=bool) 

在效果astype在施加轉換方法到所述陣列的每個元素。我們還可以定義__int____add__,這表明向自定義類添加功能比向數組類本身添加功能要容易。我不希望獲得與原生類型相同的速度。

+1

'def __bool __(self):return self.active' - 這似乎在明顯的情況下表現自己......好吧......對於'astype(bool)'無論如何... –

+0

是的,它確實有效; 'items.astype(布爾)'返回相同的數組。像這樣的數組方法在對象數組上工作,如果對象本身實現適當的方法的話。向您自己的類添加功能比向數組類添加更容易。 – hpaulj