Igor Rivin
Igor Rivin

Reputation: 4864

2D slicing confusion

Suppose I have a two dimensional numpy array. For example:

dog = np.random.rand(3, 3)

Now, I can extract the intersection of the first and second row and the second and third column of dog thus:

dog[:2, 1:]

I can also do

dog[[0, 1], 1:]

or

dog[:2, [1, 2]]

But I CAN NOT do

dog[[0, 1], [1, 2]] 

That returns a one dimensional array of the [0, 1] and [1, 2] elements of dog. And this seems to mean that to extract that principal submatrix which is the intersection of the first and last row of dog and the first and last column I have to something gross like:

tmp = dog[[0, 2], :]
ans = tmp[:, [0, 2]]

Is there some more civilized way extracting submatrices? The obvious solution dog[[0, 2], [0, 2]] does work in Julia.

Upvotes: 0

Views: 74

Answers (1)

hpaulj
hpaulj

Reputation: 231665

In [94]: dog = np.arange(9).reshape(3,3)
In [95]: dog
Out[95]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

the slice block:

In [96]: dog[:2,1:]
Out[96]: 
array([[1, 2],
       [4, 5]])

With 2 lists (1d arrays), we select the diagonal from that block:

In [97]: dog[[0,1],[1,2]]
Out[97]: array([1, 5])

But if we change the first to (2,1) array, it broadcasts with the (2,) to select at (2,2) block:

In [98]: dog[[[0],[1]],[1,2]]
Out[98]: 
array([[1, 2],
       [4, 5]])

In [99]: dog[np.ix_([0,1],[1,2])]
Out[99]: 
array([[1, 2],
       [4, 5]])

ix_ turns the 2 lists into (2,1) and (1,2) arrays:

In [100]: np.ix_([0,1],[1,2])
Out[100]: 
(array([[0],
        [1]]),
 array([[1, 2]]))

The diagonal selection in [97] follows the same logic: (2,) and (2,) => (2,)

I don't know about Julia, but MATLAB lets us use [97] like syntax to select the block, but to get the 'diagonal' we have to convert the indices to a flat index, the equivalent of:

In [104]: np.ravel_multi_index(([0,1],[1,2]),(3,3))
Out[104]: array([1, 5])
In [105]: dog.flat[_]
Out[105]: array([1, 5])

So what's easy in numpy is harder in MATLAB, and visa versa. Once you understand broadcasting the numpy approach is logical and general.

Upvotes: 1

Related Questions