1

This is my first Question here, let me know if I could've done anything better.

I'm trying to do a element-wise operation between two arrays, but the broadcasting wont work like I want it to.

I have an array of shape (N,4).

square_list = np.array([[1,2,255,255], [255,255,4,4], [255,255,8,8], [255,255,16,16], [255,255,8,4], [255,1,8,8], [1,255,8,8]], dtype='B')

I also have an array of shape (4,).

square = np.array([1, 8, 8, 1], dtype='B')

What I am able to do is compare my square against each element in the square_list and it is being broadcast into shape (N,4) as expected.

Now I want to compare my square in each possible rotation against the square_list. I've written a function which returns an array of shape (4,4), which contains each possible rotation.

square.rotations
    array([[1, 8, 8, 1],
           [1, 1, 8, 8],
           [8, 1, 1, 8],
           [8, 8, 1, 1]], dtype=uint8)

I know how to do this using a loop. I'd prefer however to use an element-wise operator that returns my desired shape.

What I get:

rotations & square_list
ValueError: operands could not be broadcast together with shapes (4,4) (6,4)

What I'd like to get:

rotations & square_list
array([[[1, 0, 8, 1],
        [1, 8, 0, 0],
        [1, 8, 8, 0],
        [1, 8, 0, 0],
        [1, 8, 8, 0],
        [1, 0, 8, 0]],
       [[1, 0, 8, 8],
        [1, 1, 0, 0],
        [1, 1, 8, 8],
        [1, 1, 0, 0],
        [1, 1, 8, 0],
        [1, 1, 8, 8]],
       [[0, 0, 1, 8],
        [8, 1, 0, 0],
        [8, 1, 0, 8],
        [8, 1, 0, 0],
        [8, 1, 0, 0],
        [8, 1, 0, 8],
        [0, 1, 0, 8]],
       [[0, 0, 1, 1],
        [8, 8, 0, 0],
        [8, 8, 0, 0],
        [8, 8, 0, 0],
        [8, 8, 0, 0],
        [8, 0, 0, 0],
        [0, 8, 0, 0]]], dtype=uint8)

This is just to visualize what I want, I don't particularly care about the order of the axis'. A shape of either (4, N, 4) or (N, 4, 4) would be great. I have the feeling that this can be achieved easily by just reshaping one of the input arrays but I couldn't figure it out.

Thanks in advance!

medium-dimensional
  • 1,974
  • 10
  • 19
Klaus
  • 40
  • 7

1 Answers1

1

Add an extra dimension to rotations:

square_list & rotations[:,None]

output:

array([[[1, 0, 8, 1],
        [1, 8, 0, 0],
        [1, 8, 8, 0],
        [1, 8, 0, 0],
        [1, 8, 8, 0],
        [1, 0, 8, 0],
        [1, 8, 8, 0]],

       [[1, 0, 8, 8],
        [1, 1, 0, 0],
        [1, 1, 8, 8],
        [1, 1, 0, 0],
        [1, 1, 8, 0],
        [1, 1, 8, 8],
        [1, 1, 8, 8]],

       [[0, 0, 1, 8],
        [8, 1, 0, 0],
        [8, 1, 0, 8],
        [8, 1, 0, 0],
        [8, 1, 0, 0],
        [8, 1, 0, 8],
        [0, 1, 0, 8]],

       [[0, 0, 1, 1],
        [8, 8, 0, 0],
        [8, 8, 0, 0],
        [8, 8, 0, 0],
        [8, 8, 0, 0],
        [8, 0, 0, 0],
        [0, 8, 0, 0]]], dtype=uint8)
mozway
  • 194,879
  • 13
  • 39
  • 75
  • Thank you for your quick reply! Do you mind adding a short explanation or a link why this works so I can figure out similar problems by myself? – Klaus May 01 '22 at 16:03
  • 1
    In your initial attempt, the dimensions were `(7, 4)` and `(4, 4)`, so no possibility to align them on both. After reshaping "rotations", it becomes `(4, 1, 4)`, so the `1` can broadcast to the `7`. Is this clear? – mozway May 01 '22 at 16:06