Reputation: 35
I have create an numpy array in which all the cells values are objects. I want to use np.where conditions but it is not working as I want to check the equivalent conditions for object attributes. The object class looks similar to the one below:
class Cell():
def __init__(self):
self.value = 'ABC'
def __repr__(self):
return self.value
Now I have 2D numpy array with all the cell equivalent to this cell class, and I want to check if cell.value == 'ABC'. The numpy array look like,
array([[M, M, M, M],
[M, 'ABC', M, M],
[M, M, M, M],
[M, M, M, 'ABC'],
[M, M, M, M]], dtype=object)
If I try to run np.where(temp == 'ABC'), I get the following output:
(array([], dtype=int64), array([], dtype=int64))
And if I run the command np.where(temp.value == 'ABC'), I get the following error:
AttributeError Traceback (most recent call last)
<ipython-input-70-073cbaaed538> in <module>
----> 1 np.where(temp.value =='ABC')
AttributeError: 'numpy.ndarray' object has no attribute 'value'
How can I use np.where with OOP?
Upvotes: 1
Views: 506
Reputation: 19332
You are comparing with an object ('ABC') from str
class with an object from '__main__.Cell'
class. (try checking with type(Cell())
A fix is simply changing type with np.array.astype()
arr = np.array([['M', Cell(),'M'],
['M', Cell(),'M'],
[Cell(),'M' ,'M']])
np.where(arr.astype(str)=='ABC')
(array([0, 1, 2]), array([1, 1, 0]))
Additionally,
You can check type of each element individually in your array by -
np.vectorize(type)(arr)
array([[<class 'str'>, <class '__main__.Cell'>, <class 'str'>],
[<class 'str'>, <class '__main__.Cell'>, <class 'str'>],
[<class '__main__.Cell'>, <class 'str'>, <class 'str'>]],
dtype=object)
Notice, that some of them are objects of class str
which you want to use for comparison but others are Cell
class objects.
Upvotes: 2
Reputation: 231530
In [38]: class Cell():
...: def __init__(self):
...: self.value = 'ABC'
...: def __repr__(self):
...: return self.value
...:
A list of these objects:
In [39]: alist = [Cell(),Cell(),Cell()]
In [40]: [c.value for c in alist]
Out[40]: ['ABC', 'ABC', 'ABC']
In [41]: alist.value
Traceback (most recent call last):
File "<ipython-input-41-e136813b0fd2>", line 1, in <module>
alist.value
AttributeError: 'list' object has no attribute 'value'
An array of the same:
In [42]: arr = np.array(alist)
In [43]: arr
Out[43]: array([ABC, ABC, ABC], dtype=object)
In [44]: arr.value
Traceback (most recent call last):
File "<ipython-input-44-bfedc572e969>", line 1, in <module>
arr.value
AttributeError: 'numpy.ndarray' object has no attribute 'value'
Same problem as with this list. Just because the elements have some attribute, it does not mean that a list or array has that attribute. That's not how Python's OOP works.
In [45]: [c.value for c in arr]
Out[45]: ['ABC', 'ABC', 'ABC']
An alternative to the list comprehension:
In [46]: np.frompyfunc(lambda x: x.value, 1,1)(arr)
Out[46]: array(['ABC', 'ABC', 'ABC'], dtype=object)
This may be convenient in some cases, but it is not faster.
Upvotes: 0
Reputation: 125
I think you need to traverse through the whole array to check if something is equal to 'ABC'. The code for the same is below:
m =[]
for i in range(temp.shape[0]):
m.append([])
for j in range(temp.shape[1]):
m[i].append(temp[i,j].value == 'ABC')
np.where(m)
In this case, you won't have the computation advantage of using np.where, as you need to traverse through the whole array using for loops.
Upvotes: 0