I'm troubled with the np.where() function. (line 7 in my example)
Background: I am programming the game "Connect Four". This insert_chip()
method accesses the variable self.board
which is an 8x8 np array of my personal dtype Chip
. If there is no chip
in an entry of self.board
, then the value is None
.
For some reason, np.where(col_entries is None)
does not return the indices of the elements that are None
. And why do I receive a different output, when I write col_entries == None
in the condition? It's not a if None
has a reference right?
def insert_chip(self, chip, col):
# slices the entries of the column into a new array
col_entries = self.board[:, col:col+1]
# checks for all unoccupied pos in this col (entries are None)
# gives double array of indexes with the form (array([row_i, ...]), array([col_i, ...]))
none_indexes = np.where(col_entries is None)
# the pos where the chip will fall is the one with the highest index
self.board[len(none_indexes[0]), col] = chip
The numpy. where() function returns the indices of elements in an input array where the given condition is satisfied.
The distinction between None and NaN in Pandas is subtle: None represents a missing entry, but its type is not numeric. This means that any column (Series) that contains a None cannot be of type numeric (e.g. int and float ). NaN , which stands for not-a-number, is a numeric type.
None is an alias for NP. newaxis. It creates an axis with length 1. This can be useful for matrix multiplcation etc.
For some reason,
np.where(col_entries is None)
does not return the indices of the elements that areNone
.
The is
operator checks if the two operands point to the same object. So here it checks if col_entries
(the matrix) is None
, it thus does not performs "broadcasting" to check if some elements in the matrix refer to None
.
In Python one can overload certain operators like <=
, ==
, etc. Numpy makes use of that to implement specific operators, such that one can write some_matrix == 0
to generate a matrix of booleans. The is
operator can not be overloaded, and so Numpy (nor any other library) has control over this. is
simply checks if the two operands refer to the same object.
Since here your col_entries
refers to a numpy array, this will always be False
, hence np.where(col_entries is None)
will always return an 1-tuple containing an empty array.
Although there are not that much objects that are equal to None
, it is still not very safe to count on that. We can vectorize the is
operator, like:
from operator import is_
np.where(np.vectorize(is_)(col_entries, None))
Make an object dtype array:
In [37]: arr = np.zeros((3,3), object)
In [39]: arr[range(3),range(3)]=None
In [40]: arr
Out[40]:
array([[None, 0, 0],
[0, None, 0],
[0, 0, None]], dtype=object)
The is None
test:
In [41]: arr is None
Out[41]: False
The == test.
In [42]: arr == None
Out[42]:
array([[ True, False, False],
[False, True, False],
[False, False, True]])
In [43]: np.where(arr == None)
Out[43]: (array([0, 1, 2]), array([0, 1, 2]))
Propagation of comparison tests in object arrays has been undergoing some changes. From a recent release_notes: https://docs.scipy.org/doc/numpy-1.15.1/release.html#comparison-ufuncs-accept-dtype-object-overriding-the-default-bool
Similar operations on a list
In [44]: alist = [0,None,0]
In [45]: alist is None
Out[45]: False
In [46]: [i is None for i in alist]
Out[46]: [False, True, False]
In [48]: alist.index(None)
Out[48]: 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With