0

I've been looking all over but I'm not really sure how to even describe what it is I want. Essentially I need to turn

np.array(
    [[0,0, 1,1, 2,2],
     [0,0, 1,1, 2,2],
     [3,3, 4,4, 5,5],
     [3,3, 4,4, 5,5]]
)

into

np.array(
    [[[0,1,2,3,4,5], [0,1,2,3,4,5]],
     [[0,1,2,3,4,5], [0,1,2,3,4,5]]
)

I think I can accomplish that using np.reshape and maybe some other stuff but if I try reshape with arguments (2,2,6) I get back

[[[0 0 1 1 2 2]
  [0 0 1 1 2 2]]

 [[3 3 4 4 5 5]
  [3 3 4 4 5 5]]]

which is not quite what I want.

2
  • are the new values in resulting arrays just indicies of the original array? Commented Sep 12, 2020 at 21:48
  • @AnnaSlastnikova no they are those values that were in the original matrix Commented Sep 12, 2020 at 21:49

3 Answers 3

2

Make your array with a couple of repeats:

In [208]: arr = np.arange(0,6).reshape(2,3)
In [209]: arr
Out[209]: 
array([[0, 1, 2],
       [3, 4, 5]])
In [210]: arr = arr.repeat(2,0).repeat(2,1)
In [211]: arr
Out[211]: 
array([[0, 0, 1, 1, 2, 2],
       [0, 0, 1, 1, 2, 2],
       [3, 3, 4, 4, 5, 5],
       [3, 3, 4, 4, 5, 5]])

Now break it into blocks which we can transpose:

In [215]: arr1 = arr.reshape(2,2,3,2)
In [216]: arr1
Out[216]: 
array([[[[0, 0],
         [1, 1],
         [2, 2]],

        [[0, 0],
         [1, 1],
         [2, 2]]],


       [[[3, 3],
         [4, 4],
         [5, 5]],

        [[3, 3],
         [4, 4],
         [5, 5]]]])
In [217]: arr1.shape
Out[217]: (2, 2, 3, 2)
In [218]: arr1.transpose(1,0,2,3)
Out[218]: 
array([[[[0, 0],
         [1, 1],
         [2, 2]],

        [[3, 3],
         [4, 4],
         [5, 5]]],


       [[[0, 0],
         [1, 1],
         [2, 2]],

        [[3, 3],
         [4, 4],
         [5, 5]]]])

Let's consolidate the middle 2 axes:

In [220]: arr1.transpose(1,0,2,3).reshape(2,6,2)
Out[220]: 
array([[[0, 0],
        [1, 1],
        [2, 2],
        [3, 3],
        [4, 4],
        [5, 5]],

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

Almost there; just need another transpose:

In [221]: arr1.transpose(1,0,2,3).reshape(2,6,2).transpose(0,2,1)
Out[221]: 
array([[[0, 1, 2, 3, 4, 5],
        [0, 1, 2, 3, 4, 5]],

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

The basic idea is to reshape the array into blocks, do a transpose, and reshape again. Here I needed another transpose, but if I choose the right one to start with I might not have needed that.

I don't know of a systematic way of doing this; there may be one, but so far I've just used a bit of trial and error when answering this kind of question. Everyone wants a different final arrangement.

Sign up to request clarification or add additional context in comments.

Comments

1

This should work:

>>> import numpy as np
>>> A = np.array(
...     [[0,0, 1,1, 2,2],
...      [0,0, 1,1, 2,2],
...      [3,3, 4,4, 5,5],
...      [3,3, 4,4, 5,5]]
... )
>>> B = a[::2,::2].flatten()
>>> B
array([0, 1, 2, 3, 4, 5])
>>> C = np.tile(b, (2,2,1))
>>> C
array([[[0, 1, 2, 3, 4, 5],
        [0, 1, 2, 3, 4, 5]],

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

We can generalize this for a given n * m matrix, that contain blocks sized n/y * m/x of identical values (so there are y rows and x columns of blocks)

def transform(A, y, x):
    dy = A.shape[0]/y
    dx = A.shape[1]/x
    B = A[::dy, ::dx].flatten()
    return np.tile(B, (y,x,1))

Comments

0

I think this is what you are looking for:

import numpy
b=numpy.array([[0,0,1,1,2,2],[0,0,1,1,2,2],[3,3,4,4,5,5],[3,3,4,4,5,5]])
c1=(b[::2,::2].flatten(),b[::2,1::2].flatten())
c2=(b[1::2,::2].flatten(),b[1::2,1::2].flatten())
c=numpy.vstack((c1,c2)).reshape((2,2,6))
print(c)

which outputs:

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

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

and for general size target array and general size input array this is the algorithm with an example of 3*3 input array:

import numpy
b=numpy.array([[0,0,1,1,2,2],[0,0,1,1,2,2],[0,0,1,1,2,2],[3,3,4,4,5,5],[3,3,4,4,5,5],[3,3,4,4,5,5]])
(m,n)=b.shape
C=b[::int(m/2),::2].flatten(),b[::int(m/2),1::2].flatten()
for i in range(1,int(m/2)):
    C=numpy.vstack((C,(b[i::int(m/2),::2].flatten(),b[i::int(m/2),1::2].flatten())))
print(C)

which outputs:

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

4 Comments

Close, I just need it generalized now. Like for an m * n matrix where the final array will be of size r * c * d
I don't understand how this is different, the algorithm remains the same: you do the same 4 iterations over the array no matter of what size it is, and no matter of what size you want... Edited the answer.
What if you want a 3 * 3? Then we would need 3 c arrays and the slice would be of the form [::3]. I'm trying to avoid for loops and just use whatever numpy has naturally
@theEpsilon I re-edited my answer, assuming this is the input pattern you were talking about.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.