Q&A library Python

How do I combine NumPy arrays into one?

Python Intermediate concatenatenumpystacking

Short answer

Use vstack to stack rows, hstack to join columns, and concatenate with an axis for the general case. The shapes must match on every axis except the one you are joining along.

The short version

np.vstack stacks arrays on top of each other (adding rows), np.hstack joins them side by side (adding columns), and np.concatenate does either when you give it an axis. The shapes must agree on every axis except the one you are joining along, or you get a shape error.

The three ways

import numpy as np

a = np.array([[1, 2]])
b = np.array([[3, 4]])

np.vstack([a, b]).shape        # (2, 2) , stacked as rows
np.hstack([a, b]).shape        # (1, 4) , joined as columns
np.concatenate([a, b], axis=0) # same as vstack
np.concatenate([a, b], axis=1) # same as hstack

vstack and hstack are readable shortcuts; concatenate with an explicit axis is the general form and is clearer when you are working in more than two dimensions.

The shape rule

To stack vertically, the arrays must have the same number of columns. To stack horizontally, the same number of rows. If they do not, NumPy raises an error about dimensions not matching.

np.vstack([np.zeros((2, 3)), np.zeros((1, 4))])
# ValueError: all the input array dimensions except for the concatenation axis must match exactly

The error message is precise: everything except the joining axis must line up. When you hit it, print the .shape of each array and the mismatch is immediately obvious.

The one-dimensional surprise

A 1D array of length 3 has shape (3,), not (1, 3), and this catches people out constantly.

np.vstack([np.array([1, 2, 3]), np.array([4, 5, 6])]).shape   # (2, 3) , works
np.hstack([np.array([1, 2, 3]), np.array([4, 5, 6])]).shape   # (6,) , flat!

vstack promotes 1D arrays to rows, so it does what you expect. hstack simply joins them end to end, giving one long flat array rather than a two-column table. If you wanted columns, reshape first.

np.column_stack([[1, 2, 3], [4, 5, 6]]).shape   # (3, 2) , pairs them as columns

column_stack is the tool that does what people usually mean by "put these side by side as columns".

Building an array in a loop

The same anti-pattern as with lists and DataFrames applies here.

# BAD: reallocates and copies the whole array every iteration
result = np.array([])
for row in rows:
    result = np.vstack([result, row])

Collect the pieces in a Python list and stack once.

pieces = [compute(row) for row in rows]
result = np.vstack(pieces)

NumPy arrays have a fixed size, so every "append" allocates a new array and copies everything. Growing one in a loop is quadratic, and on any real number of iterations it is dramatically slower than building a list first.

When to use pandas instead

If your arrays represent labelled, heterogeneous data, a DataFrame with pd.concat handles alignment by column name and copes with differing columns, which raw NumPy cannot. Use NumPy stacking for homogeneous numeric blocks where position is the only meaning.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project