# Manipulating numpy arrays (concatenating inner sub-arrays)

I have a question of manipulating numpy arrays. Say, given a 3-d array in the form `np.array([[[1,2],[3,4]], [[5,6],[7,8]]])` which is a `(2,2,2)` array. I want to manipulate it into a `(2,4)` array such that `a = np.array([[1,2,5,6],[3,4,7,8]])`. I want to know is there any built-in methods of numpy particularly dealing with problems like this and can be easily generalized.

EDITED: Thank you all guys’ answers. They all rock! I thought I should clarify what I mean by “easily generalized” in the original post. Suppose given a `(6,3,2,3)` array (this is the actual challenge I am facing)

```a = array([[[[ 10,  20,  30],
[ 40,  40,  20]],

[[ 22,  44,  66],
[ 88,  88,  44]],

[[ 33,  66,  99],
[132, 132,  66]]],

[[[ 22,  44,  66],
[ 88,  88,  44]],

[[ 54, 108, 162],
[216, 216, 108]],

[[ 23,  46,  69],
[ 92,  92,  46]]],

[[[ 14,  28,  42],
[ 56,  56,  28]],

[[ 25,  50,  75],
[100, 100,  50]],

[[ 33,  66,  99],
[132, 132,  66]]],

[[[ 20,  40,  60],
[ 80,  80,  40]],

[[ 44,  88, 132],
[176, 176,  88]],

[[ 66, 132, 198],
[264, 264, 132]]],

[[[ 44,  88, 132],
[176, 176,  88]],

[[108, 216, 324],
[432, 432, 216]],

[[ 46,  92, 138],
[184, 184,  92]]],

[[[ 28,  56,  84],
[112, 112,  56]],

[[ 50, 100, 150],
[200, 200, 100]],

[[ 66, 132, 198],
[264, 264, 132]]]])
```

I want to massage it into a `(3,3,2,2,3)` array such that for`a[0,:,:,:,:]`

```a[0,0,0,:,:] = np.array([[10,20,30],[40,40,20]]);
a[0,1,0,:,:] = np.array([[22,44,66],[88,88,44]]);
a[0,2,0,:,:] = np.array([[33,66,99],[132,132,66]]);
a[0,0,1,:,:] = np.array([[20,40,60],[80,80,40]]);
a[0,1,1,:,:] = np.array([[44,88,132],[176,176,88]]);
a[0,2,1,:,:] = np.array([[66,132,198],[264,264,132]]).
```

In short, the last 3 biggest blocks should “merge” with first 3 biggest blocks to form 3 `(3,2)` blocks. The rest of 2 blocks i.e., (`a[1,:,:,:,:]`, `a[2,:,:,:,:]`) follow the same pattern.

From your new update, you can do the following using np.lib.stride_tricks.as_strided:

```>>> np.lib.stride_tricks.as_strided(a, shape=(3,3,2,2,3), strides=(72,24,216,12,4))
array([[[[[ 10,  20,  30],
[ 40,  40,  20]],

[[ 20,  40,  60],
[ 80,  80,  40]]],

[[[ 22,  44,  66],
[ 88,  88,  44]],

[[ 44,  88, 132],
[176, 176,  88]]],

[[[ 33,  66,  99],
[132, 132,  66]],

[[ 66, 132, 198],
[264, 264, 132]]]],

[[[[ 22,  44,  66],
[ 88,  88,  44]],

[[ 44,  88, 132],
[176, 176,  88]]],

[[[ 54, 108, 162],
[216, 216, 108]],

[[108, 216, 324],
[432, 432, 216]]],

[[[ 23,  46,  69],
[ 92,  92,  46]],

[[ 46,  92, 138],
[184, 184,  92]]]],

[[[[ 14,  28,  42],
[ 56,  56,  28]],

[[ 28,  56,  84],
[112, 112,  56]]],

[[[ 25,  50,  75],
[100, 100,  50]],

[[ 50, 100, 150],
[200, 200, 100]]],

[[[ 33,  66,  99],
[132, 132,  66]],

[[ 66, 132, 198],
[264, 264, 132]]]]])
```

Explanation:

Take another example: a small array `q` and our desired output after changing `q`:

```>>> q = np.arange(12).reshape(4,3,-1)
>>> q
array([[[ 0],
[ 1],
[ 2]],

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

[[ 6],
[ 7],
[ 8]],

[[ 9],
[10],
[11]]])
# desired output:
# shape = (2, 3, 2)
array([[[ 0,  6],
[ 1,  7],
[ 2,  8]],

[[ 3,  9],
[ 4, 10],
[ 5, 11]]])
```

Here we are using numpy strides to achieve this. Let’s check for `q`‘s strides:

```>>> q.strides
(12, 4, 4)
```

In our output, all strides should remain the same, except the third stride, because in the third dimension we need to stack with the values from bottom half of `q`, ie: `6` is put next to `0`, `7` next to `1` and so on…

So, how “far” is it from `0` to `6` ? Or in another word, how far is it from `q[0,0,0]` to `q[2,0,0]` ?

```# obviously, distance = [2,0,0] - [0,0,0] = [2,0,0]
bytedistance = np.sum(np.array([2,0,0])*q.strides)
# 2*12 + 0*4 + 0*4 = 24 bytes
```

Okay then `new_strides = (12, 4, 24)` and hence we got:

```>>> np.lib.stride_tricks.as_strided(q, shape=(2,3,2), strides=new_strides)
array([[[ 0,  6],
[ 1,  7],
[ 2,  8]],

[[ 3,  9],
[ 4, 10],
[ 5, 11]]])
```

```a.strides = (72,24,12,4)