2

I have a 3D np.array

arr = np.array([ 
                [ [0, 205, 25], [210, 150, 30], [0, 0, 0], [1, 2, 3], [4, 5, 6], [7, 8, 9] ],
                [ [0, 255, 0], [255, 40, 0], [0, 0, 200], [7, 8, 9], [10, 11, 12], [120, 51, 58] ],
                [ [0, 0, 30], [0, 40, 0], [200, 100, 20], [12, 13, 14], [15, 16, 17], [13, 78, 84], ],
                [ [0, 205, 25], [210, 150, 30], [0, 0, 0], [1, 2, 3], [4, 5, 6], [7, 8, 9] ],
                [ [0, 255, 0], [255, 40, 0], [0, 0, 200], [7, 8, 9], [10, 11, 12], [120, 51, 58] ],
                [ [0, 0, 30], [0, 40, 0], [200, 100, 20], [12, 13, 14], [15, 16, 17], [13, 78, 84], ],
                [ [0, 205, 25], [210, 150, 30], [0, 0, 0], [1, 2, 3], [4, 5, 6], [7, 8, 9] ],
                [ [0, 255, 0], [255, 40, 0], [0, 0, 200], [7, 8, 9], [10, 11, 12], [120, 51, 58] ],
                [ [0, 0, 30], [0, 40, 0], [200, 100, 20], [12, 13, 14], [15, 16, 17], [13, 78, 84], ],
              ])

And I need to split it to 3x2x3 3D arrays

[ [0, 205, 25], [210, 150, 30],    [0, 0, 0], [1, 2, 3],             [4, 5, 6], [7, 8, 9] ],
[ [0, 255, 0],  [255, 40, 0],      [0, 0, 200], [7, 8, 9],           [10, 11, 12], [120, 51, 58] ],
[ [0, 0, 30],   [0, 40, 0],        [200, 100, 20], [12, 13, 14],     [15, 16, 17], [13, 78, 84], ],

[ [0, 205, 25], [210, 150, 30],    [0, 0, 0], [1, 2, 3],             [4, 5, 6], [7, 8, 9] ],
[ [0, 255, 0],  [255, 40, 0],      [0, 0, 200], [7, 8, 9],           [10, 11, 12], [120, 51, 58] ],
[ [0, 0, 30],   [0, 40, 0],        [200, 100, 20], [12, 13, 14],     [15, 16, 17], [13, 78, 84], ],

[ [0, 205, 25], [210, 150, 30],    [0, 0, 0], [1, 2, 3],             [4, 5, 6], [7, 8, 9] ],
[ [0, 255, 0],  [255, 40, 0],      [0, 0, 200], [7, 8, 9],           [10, 11, 12], [120, 51, 58] ],
[ [0, 0, 30],   [0, 40, 0],        [200, 100, 20], [12, 13, 14],     [15, 16, 17], [13, 78, 84], ],

to get a 4D array with these 3D blocks I've selected by spaces. Zero element must be

[ 
    [[0, 205, 25], [210, 150, 30]],
    [[0, 255, 0], [255, 40, 0]],
    [[0, 0, 30], [0, 40, 0]] 
]

and so on.

I've read this question but still don't undersatand how to do this (Why we need to reshape, transpose and reshape again and what a magical numbers in transpose()). I could try to write my own function but I want to know how to do it native way.

Pavel Antspovich
  • 1,111
  • 1
  • 11
  • 27

1 Answers1

2

You can reshape and transpose it

arr.reshape(3, 3, 3, 2, 3).transpose(2, 0, 1, 3, 4)
# array([[[[[  0, 205,  25],
#           [210, 150,  30]],
# 
#          [[  0, 255,   0],
#           [255,  40,   0]],
# 
#          [[  0,   0,  30],
#           [  0,  40,   0]]],
# 
# 
#         [[[  0, 205,  25],
#           [210, 150,  30]],
# 
#          [[  0, 255,   0],
#           [255,  40,   0]],
# 
#          [[  0,   0,  30],
#           [  0,  40,   0]]],
# 
# 
# ...
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
  • Would you explain these numbers? – Pavel Antspovich Sep 27 '19 at 12:45
  • 2
    They're the numbers you gave in your question. `-1` means "infer this value from the remaining numbers" – Nils Werner Sep 27 '19 at 12:46
  • 1
    Specifically, reading the linked documentation for `reshape`, it is "The new shape should be compatible with the original shape. If an integer, then the result will be a 1-D array of that length. One shape dimension can be -1. In this case, the value is inferred from the length of the array and remaining dimensions." – KDecker Sep 27 '19 at 12:48
  • I need some another order. Zero element must be ```[ [[0, 205, 25], [210, 150, 30]], [[0, 255, 0], [255, 40, 0]], [[0, 0, 30], [0, 40, 0]] ] – Pavel Antspovich Sep 27 '19 at 12:56
  • @NilsWerner, such a strange thing. I have another outpit [[[ 0 205 25] [210 150 30] [ 0 0 0] [ 1 2 3] [ 4 5 6] [ 7 8 9]] [[ 0 255 0] [255 40 0] [ 0 0 200] [ 7 8 9] [ 10 11 12] [120 51 58]] ...] – Pavel Antspovich Sep 27 '19 at 13:38
  • There must be something wrong in your reshaping operation, axis `-2` has a size of `6`, but my call to `reshape()` has no `6`. – Nils Werner Sep 27 '19 at 13:44
  • @NilsWerner found out that I need to use arr = arr.reshape(3, 3, 3, 2, 3).transpose(2, 0, 1, 3, 4). numpy==1.17.2 – Pavel Antspovich Sep 27 '19 at 15:50
  • That's **exactly** the solution I posted? – Nils Werner Sep 27 '19 at 17:02