Roland
Roland

Reputation: 101

python numpy subtract elements that are matrices

Using numpy, how can I subtract the elements of a numpy array that are matrices by each other?

a = np.array([ [ [1., 2., 3.],    [4., 5., 6.],    [7., 8., 9.]    ],
               [ [20., 21., 22.], [23., 24., 25.], [26., 27., 28.] ],
               [ [30., 31., 32.], [33., 34., 35.], [36., 37., 38.] ]
             ])

or in plain English:

a = ([matrix1], [matrix2], [matrix3])

I want to get a np.array that calculates as follows:

[matrix1-matrix1][matrix1-matrix2][matrix1-matrix3]

[matrix2-matrix1][matrix2-matrix2][matrix2-matrix3]

[matrix3-matrix1][matrix3-matrix2][matrix3-matrix3]

Diagonal will be a matrix with zero values in the matrix.

How can I accomplish this?

Upvotes: 4

Views: 500

Answers (1)

hpaulj
hpaulj

Reputation: 231385

Your a is a 3d array

In [258]: a = np.array([ [ [1., 2., 3.],    [4., 5., 6.],    [7., 8., 9.]    ],
   .....:                [ [20., 21., 22.], [23., 24., 25.], [26., 27., 28.] ],

   .....:                [ [30., 31., 32.], [33., 34., 35.], [36., 37., 38.] ]
   .....:              ])
In [259]: a.shape
Out[259]: (3, 3, 3)

2d arrays can be accessed with indexing

In [260]: a[0,:,:]
Out[260]: 
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.],
       [ 7.,  8.,  9.]])

and a tuple of 3 2d arrays can be obtained with:

In [261]: (a[0,:,:],a[1,:,:],a[2,:,:])
Out[261]: 
(array([[ 1.,  2.,  3.],
        [ 4.,  5.,  6.],
        [ 7.,  8.,  9.]]), 
 array([[ 20.,  21.,  22.],
        [ 23.,  24.,  25.],
        [ 26.,  27.,  28.]]), 
 array([[ 30.,  31.,  32.],
        [ 33.,  34.,  35.],
        [ 36.,  37.,  38.]]))

This is equivalent to your (matrix1, matrix2, matrix3) expression. I'm using 2d array instead of matrix because numpy has an array subclass called matrix, so the term can be confusing.

A way to generate your subarray cross-difference is with broadcasting. I use the None syntax to expand the dimension of a.

In [262]: a[:,None,:,:]-a[None,:,:,:]
Out[262]: 
array([[[[  0.,   0.,   0.],
         [  0.,   0.,   0.],
         [  0.,   0.,   0.]],

        [[-19., -19., -19.],
         [-19., -19., -19.],
         [-19., -19., -19.]],

        ...

        [[ 10.,  10.,  10.],
         [ 10.,  10.,  10.],
         [ 10.,  10.,  10.]],

        [[  0.,   0.,   0.],
         [  0.,   0.,   0.],
         [  0.,   0.,   0.]]]])
In [263]: _.shape
Out[263]: (3, 3, 3, 3)

The shape of this new array is 4d, which can be thought of as a 3x3 array of 3x3 arrays. And yes, the diagonal elements A[i,i,:,:] are all 0s.

In [264]: A=a[:,None,:,:]-a[None,:,:,:]
In [265]: A[2,2,:,:]
Out[265]: 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

Upvotes: 2

Related Questions