Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

np.where(condition is None) not equal to np.where(condition == None)

Tags:

python

numpy

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
like image 499
Philipp Avatar asked Nov 16 '18 20:11

Philipp


People also ask

What does NP where () return?

The numpy. where() function returns the indices of elements in an input array where the given condition is satisfied.

Is NaN none in pandas?

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.

What is none in Numpy array?

None is an alias for NP. newaxis. It creates an axis with length 1. This can be useful for matrix multiplcation etc.


2 Answers

For some reason, np.where(col_entries is None) does not return the indices of the elements that are None.

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))
like image 90
Willem Van Onsem Avatar answered Nov 14 '22 23:11

Willem Van Onsem


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
like image 35
hpaulj Avatar answered Nov 14 '22 23:11

hpaulj