Search code examples
pythonarraysnumpybroadcastdivide

How to divide an n-dimensional array by the first value from a dimension


Given an array of dimension N how do I divide all values in the array by the first value from a selected dimension?

Example code:

import numpy as np
A = np.random.randint(1, 10, size=(3,3,3))
B = A[:,:,0]
C = np.divide(A,B)
A
print()
B
print()
C
print()
C[:,:,0]

Output:

array([[[1, 8, 5],
        [3, 6, 5],
        [5, 4, 2]],

       [[6, 2, 9],
        [4, 2, 2],
        [5, 6, 8]],

       [[3, 3, 1],
        [2, 7, 7],
        [6, 4, 6]]])


array([[1, 3, 5],
       [6, 4, 5],
       [3, 2, 6]])


array([[[1.        , 2.66666667, 1.        ],
        [0.5       , 1.5       , 1.        ],
        [1.66666667, 2.        , 0.33333333]],

       [[6.        , 0.66666667, 1.8       ],
        [0.66666667, 0.5       , 0.4       ],
        [1.66666667, 3.        , 1.33333333]],

       [[3.        , 1.        , 0.2       ],
        [0.33333333, 1.75      , 1.4       ],
        [2.        , 2.        , 1.        ]]])


array([[1.        , 0.5       , 1.66666667],
       [6.        , 0.66666667, 1.66666667],
       [3.        , 0.33333333, 2.        ]])

I was expecting the final output from C[:,:,0] to be all 1's. I guess it has to do with the broadcasting of B but I don't think I understand why it isn't broadcasting B into a shape (3,3,3) where it is replicated along dimension 2.


Solution

  • To get your expected results you could reshape your B array to:

    B = A[:,:,0].reshape(3,-1, 1)
    

    Then when you divide you will get a result like:

    array([[[1.        , 0.11111111, 0.11111111],
            [1.        , 0.25      , 0.5       ],
            [1.        , 0.88888889, 0.44444444]],
    
           [[1.        , 0.88888889, 1.        ],
            [1.        , 1.8       , 1.6       ],
            [1.        , 4.5       , 0.5       ]],
    
           [[1.        , 0.66666667, 0.5       ],
            [1.        , 1.125     , 0.75      ],
            [1.        , 0.5       , 2.25      ]]])
    

    You could also maintain the proper dimension for broadcasting by taking B as:

    B = A[:,:,0:1]