In [34]: arr=np.random.random((4,4))
In [35]: arr
Out[35]:
array([[ 0.00750932, 0.47917318, 0.39813503, 0.11755234],
[ 0.30330724, 0.67527229, 0.71626247, 0.22526589],
[ 0.5821906 , 0.2060713 , 0.50149411, 0.0328739 ],
[ 0.42066294, 0.88529916, 0.09179092, 0.39389844]])
This gives the minor of arr
, with the 1st row and 2nd column removed:
In [36]: arr[np.array([0,2,3])[:,np.newaxis],np.array([0,1,3])]
Out[36]:
array([[ 0.00750932, 0.47917318, 0.11755234],
[ 0.5821906 , 0.2060713 , 0.0328739 ],
[ 0.42066294, 0.88529916, 0.39389844]])
So, you could use something like this:
def minor(arr,i,j):
# ith row, jth column removed
return arr[np.array(range(i)+range(i+1,arr.shape[0]))[:,np.newaxis],
np.array(range(j)+range(j+1,arr.shape[1]))]
Regarding how this works:
Notice the shape of the index arrays:
In [37]: np.array([0,2,3])[:,np.newaxis].shape
Out[37]: (3, 1)
In [38]: np.array([0,1,3]).shape
Out[38]: (3,)
The use of [:,np.newaxis]
was simply to give the first array the shape (3,1).
Since these are numpy arrays (instead of say, slices), numpy uses so-called "fancy" indexing. The rules for fancy indexing require the shape of the two arrays to be the same, or, when they are not the same, to use broadcasting to "pump-up" the shapes so that they do match.
In this case, the second array's shape (3,) is pumped up to (1,3). But
(3,1) and (1,3) do not match, so (3,1) is pumped up to (3,3) and (1,3) is pumped up to (3,3).
Ah, at last, the two numpy arrays have (after broadcasting) the same shape, (3,3).
Numpy takes arr[<array of shape (3,3)>, <array of shape (3,3)>]
and returns an array of shape (not surprisingly) (3,3).
The (i,j)-th element of the returned array will be
arr[(i,j)-th element of first array, (i,j)-th element of second array]
where the first and second arrays look (conceptually) like this:
first array: second array:
[[0 0 0], [[0, 1, 3],
[2 2 2], [0, 1, 3],
[3 3 3]] [0, 1, 3]]