Why does boolean indexing of a 2D NumPy array produces 1d array?

Viewed 3154

I was experimenting with boolean indexing in NumPy and came across this which is confusing me:

import numpy as np

np.random.seed(0)

Created a 7 x 4 array:

data = np.random.rand(7, 4) 

[[ 0.5488  0.7152  0.6028  0.5449]

 [ 0.4237  0.6459  0.4376  0.8918]

 [ 0.9637  0.3834  0.7917  0.5289]

 [ 0.568   0.9256  0.071   0.0871]

 [ 0.0202  0.8326  0.7782  0.87  ]

 [ 0.9786  0.7992  0.4615  0.7805]

 [ 0.1183  0.6399  0.1434  0.9447]]

Created a boolean array also 7 x 4:

bool_array = 

         ([[True,False,False,True],
          [True,False,False,True],
          [True,False,False,True],
          [True,False,False,True],
          [True,False,False,True],
          [True,False,False,True],
          [True,False,False,True]])


bool_array = np.array(bool_array)

data[bool_array]

Output:

[ 0.5488  0.5449  0.4237  0.8918  0.9637  0.5289  0.568   0.0871  0.0202
  0.87    0.9786  0.7805  0.1183  0.9447]

How can this be explained? I reasoned it as follows: the number of rows is the same (i.e. 7). For each row, True is found at positions 0 and 3 (i.e. 2 values). Thus I end up getting a 1 x 14 matrix. I was expecting a 7 x 2 matrix though.

Could someone please clarify how this is evaluated to give a 1 x 14 matrix?

1 Answers

Numpy has no a-priori way of knowing where the True elements of your mask will be. It is purely happenstance that your selection is aligned so neatly in columns.

To understand why the result is raveled into a 1D array, imagine how to handle the case where you have two selections in each row, but not always from the same column. Now imagine a case where the number of selections in each row is different, possibly with some rows completely empty. Numpy has to be able to handle all these cases consistently. It would be much slower and would cause a lot of problems to return an array of different shape depending on the contents of your mask.

To make the selection of the columns you want, use the appropriate index:

a[:, ::3]

OR

a[:, [0, 3]]
Related