I am confused about a operation of numpy, which using a matrix as index, like:
# a and b both are matrix:
a[b] = 0.0
The complete code are as following.
import numpy as np
a = np.mat('1 1; 1 2')
b = np.mat('0 0; 1 1')
print("a: ", a)
print("b: ", b)
a[~b] = 0.0
print("a: ", a)
And I get result are as following, but I don't know why.
a:
[[1 1]
[1 2]]
b:
[[0 0]
[1 1]]
a:
[[0 0]
[0 0]]
CodePudding user response:
The ~
is not something we use much with numpy - so lets check that by itself:
In [184]: ~b
Out[184]:
matrix([[-1, -1],
[-2, -2]], dtype=int32)
Negative indices "count" from the end.
In [185]: a[~b]
Out[185]:
matrix([[[1, 2],
[1, 2]],
[[1, 1],
[1, 1]]])
In [186]: a[~b].shape
Out[186]: (2, 2, 2)
This result puzzles me, because np.matrix
is supposed to restricted to 2d.
We are trying to discourage the use of np.matrix
, but if I convert a
and b
to ndarray
, the results are the same:
In [189]: a = np.mat('1 1; 1 2').A
...: b = np.mat('0 0; 1 1').A
In [192]: a[~b]
Out[192]:
array([[[1, 2],
[1, 2]],
[[1, 1],
[1, 1]]])
indexing with an array, acts just on one dimension, here the first; so it's using a (2,2) array to index the first dimension of a
, resulting in a (2,2,2). This action would be clearer if the dimensions weren't all 2.
In [197]: a[~b, :]
Out[197]:
array([[[1, 2], # index is [-1,-1], the last row
[1, 2]],
[[1, 1], # index is [-2,-2], the 2nd to last row (first)
[1, 1]]])
Since this indexing selects both rows, when used as a setter, both rows are set to 0. So this is puzzling largely because ~b
produces a numeric index array.
I wonder if instead, this code was meant to do boolean array indexing.
In [203]: b.astype(bool)
Out[203]:
array([[False, False],
[ True, True]])
Now ~
is a logical not:
In [204]: ~(b.astype(bool))
Out[204]:
array([[ True, True],
[False, False]])
Indexing with a boolean that matches in shape, selects/or/not on an element by element basis:
In [205]: a[~(b.astype(bool))]
Out[205]: array([1, 1])
In [206]: a[(b.astype(bool))]
Out[206]: array([1, 2])
Now the the 0 assignment just sets the first row.
In [207]: a[~(b.astype(bool))]=0
In [208]: a
Out[208]:
array([[0, 0],
[1, 2]])
The boolean array indexing would be clear with this example:
In [211]: b = np.array([[0,1],[1,0]], bool)
In [212]: b
Out[212]:
array([[False, True],
[ True, False]])
In [213]: a = np.arange(1,5).reshape(2,2); a
Out[213]:
array([[1, 2],
[3, 4]])
In [214]: a[b] # select the opposite corners
Out[214]: array([2, 3])
In [215]: a[~b] # select the diagonal
Out[215]: array([1, 4])