6
\$\begingroup\$

Suppose I have a H*W numpy array like this (H=3 and W=2):

[[0 1]
 [2 3]
 [4 5]]

I would like to replace each element with a matrix of M*N repeated element (M=2 and N=3):

[[[[0 0 0]
   [0 0 0]]

  [[1 1 1]
   [1 1 1]]]


 [[[2 2 2]
   [2 2 2]]

  [[3 3 3]
   [3 3 3]]]


 [[[4 4 4]
   [4 4 4]]

  [[5 5 5]
   [5 5 5]]]]

My current code first turn each element into a 2D matrix by calling expand_dims() twice, and then expand these matrices using repeat() twice too:

import numpy as np

H, W, M, N = 3, 2, 2, 3

array = np.arange(H * W).reshape(H, W)

array = np.expand_dims(array, axis=2)
array = np.expand_dims(array, axis=3)
array = np.repeat(array, M, axis=2)
array = np.repeat(array, N, axis=3)

Is there a more straightforward and elegant way to obtain the same result?

\$\endgroup\$
  • \$\begingroup\$ It looks good to me as written. There's at least two ways to criticize such code. One way is in your question, essentially "is it understandable?". Another would be, "is it performant?". We're doing lots of reads & writes, copying from src to dst matrix. Combining your last pair of ops into a single operation would be desirable, so source values are read once and written once to the ultimate destination address. \$\endgroup\$ – J_H Jan 1 '18 at 18:40
  • \$\begingroup\$ @J_H Thanks for your comment. Do you know of a way to "combine the last pair of ops into a single operation"? \$\endgroup\$ – Delgan Jan 1 '18 at 18:50
  • 1
    \$\begingroup\$ Using nested loops: "yes". Using a simple numpy expression, "no", else I'd have posted an answer instead of a comment. I'll leave that to someone better versed in numpy details. \$\endgroup\$ – J_H Jan 1 '18 at 19:03
1
\$\begingroup\$

One answer would be:

import numpy as np

H, W, M, N = 3, 2, 2, 3
arr = np.arange(H * W).reshape(H, W)

np.repeat(arr, M*N).reshape(H,W,M,N)

Which gives the output:

array([[[[0, 0, 0],
         [0, 0, 0]],

        [[1, 1, 1],
         [1, 1, 1]]],

       [[[2, 2, 2],
         [2, 2, 2]],

        [[3, 3, 3],
         [3, 3, 3]]],

       [[[4, 4, 4],
         [4, 4, 4]],

        [[5, 5, 5],
         [5, 5, 5]]]])
\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer. Does anyone know why it could have been downvoted? \$\endgroup\$ – Delgan Jan 2 '18 at 14:52
  • \$\begingroup\$ @delgan Probably because I don't engage in improving your code, but am only providing an answer. \$\endgroup\$ – robogast Jan 2 '18 at 15:38
  • \$\begingroup\$ Your code is fast and elegant, just what I was looking for. Thanks again! \$\endgroup\$ – Delgan Jan 2 '18 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.