Reputation: 6569
I'm trying to rewrite a function using numpy which is originally in MATLAB. There's a logical indexing part which is as follows in MATLAB:
X = reshape(1:16, 4, 4).';
idx = [true, false, false, true];
X(idx, idx)
ans =
1 4
13 16
When I try to make it in numpy, I can't get the correct indexing:
X = np.arange(1, 17).reshape(4, 4)
idx = [True, False, False, True]
X[idx, idx]
# Output: array([6, 1, 1, 6])
What's the proper way of getting a grid from the matrix via logical indexing?
Upvotes: 6
Views: 1389
Reputation: 58915
In numpy
this is called fancy indexing
. To get the items you want you should use a 2D
array of indices.
You can use an outer
to make from your 1D idx
a proper 2D
array of indices. The outers, when applied to two 1D
sequences, compare each element of one sequence to each element of the other. Recalling that True*True=True
and False*True=False
, the np.multiply.outer()
, which is the same as np.outer()
, can give you the 2D
indices:
idx_2D = np.outer(idx,idx)
#array([[ True, False, False, True],
# [False, False, False, False],
# [False, False, False, False],
# [ True, False, False, True]], dtype=bool)
Which you can use:
x[ idx_2D ]
array([ 1, 4, 13, 16])
In your real code you can use x=[np.outer(idx,idx)]
but it does not save memory, working the same as if you included a del idx_2D
after doing the slice.
Upvotes: 2
Reputation: 80346
In [1]: X = np.arange(1, 17).reshape(4, 4)
In [2]: idx = np.array([True, False, False, True]) # note that here idx has to
# be an array (not a list)
# or boolean values will be
# interpreted as integers
In [3]: X[idx][:,idx]
Out[3]:
array([[ 1, 4],
[13, 16]])
Upvotes: 4
Reputation: 124563
You could also write:
>>> X[np.ix_(idx,idx)]
array([[ 1, 4],
[13, 16]])
Upvotes: 7