pythonarraysnumpymultidimensional-arrayconcatenation

Why can't I stack 3D arrays with np.concatenate in numpy, while 1D and 2D arrays work?


I'm working with 3D numpy arrays and having trouble stacking two of them. Here’s what I’m trying to do:

import numpy as np

grid = np.arange(16).reshape((1, 4, 4))
grid2 = grid[:, :-1, ::-1].copy()

I expected to be able to stack grid and grid2 with np.concatenate on axis=0, like this:

np.concatenate((grid, grid2), axis=0)

But it doesn’t work, nor do np.vstack or np.dstack (I observed that vstack only works on 1D and 2D arrays). I’ve checked the shapes, and I thought they’d align since they’re both derived from grid, but it’s not cooperating.

The goal here is not to reverse all rows and columns, but to only use the first 3 rows of the original grid array, with just the columns reversed. That's why I used grid[:, :-1, ::-1].copy() to keep the rows intact while only switching the columns.

Attempting to concatenate grid and grid2 along axis=0 fails with a ValueError:

ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 4 and the array at index 1 has size 3

Here's an example of a simpler concatenation that does work as expected:

x = np.arange(1, 9).reshape((2, 4))
y = np.arange(4)
np.vstack((x, y))  # Works perfectly

Why does stacking grid and grid2 fail, while simpler cases like x and y work fine? Is there a specific rule or limitation in numpy that I’m missing here?


Solution

  • In this particular case, you could use hstack:

    np.hstack([grid, grid2])
    

    For a generic case you should concatenate on axis=1 (all other dimensions must be equal):

    np.concatenate([grid, grid2], axis=1)
    

    Output:

    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11],
            [12, 13, 14, 15],
            [ 3,  2,  1,  0],
            [ 7,  6,  5,  4],
            [11, 10,  9,  8]]])
    

    Equality of dimensions for concatenate:

    grid.shape    # (1, 4, 4)
    grid2.shape   # (1, 3, 4)
                  #     └──── only possible dimension for concatenate
    

    NB. as noted in comments, if your input is really:

    grid = np.arange(16).reshape((1, 4, 4))
    grid2 = grid[:, ::-1, ::-1].copy()
    

    Then concatenate on axis=0 can work since the other dimensions are now equal:

    np.concatenate([grid, grid2], axis=0)
    
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11],
            [12, 13, 14, 15]],
    
           [[15, 14, 13, 12],
            [11, 10,  9,  8],
            [ 7,  6,  5,  4],
            [ 3,  2,  1,  0]]])
    
    grid.shape    # (1, 4, 4)
    grid2.shape   # (1, 4, 4)  # any axis can be used to concatenate