Stacking arrays is a fundamental operation for combining multiple arrays into a single higher-dimensional array — either along a new axis (stacking) or an existing one (concatenation). In NumPy and Dask, np.stack()/da.stack() adds a new axis, while np.concatenate()/da.concatenate() joins along an existing axis. In 2026, stacking remains essential for data preparation — combining time series channels, stacking image batches for ML, merging simulation runs, aligning multi-sensor readings, or building feature matrices — with Dask enabling scalable stacking of large/out-of-core arrays and xarray providing labeled stacking with dimension management.
Here’s a complete, practical guide to stacking arrays in Python: NumPy stack vs concatenate, Dask equivalents, axis handling, real-world patterns (time series, images, batches), and modern best practices with chunk alignment, memory efficiency, type hints, and Polars/xarray equivalents.
NumPy stacking — np.stack() creates new axis; np.concatenate() joins existing.
import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
# Stack along new axis (default axis=0)
stacked = np.stack([arr1, arr2]) # shape (2, 2, 2)
print(stacked.shape) # (2, 2, 2)
# Stack along axis=1 (columns)
stacked_axis1 = np.stack([arr1, arr2], axis=1) # (2, 2, 2) ? variables × time × features
print(stacked_axis1)
# Concatenate along existing axis
concat_rows = np.concatenate([arr1, arr2], axis=0) # (4, 2)
concat_cols = np.concatenate([arr1, arr2], axis=1) # (2, 4)
Dask stacking — lazy, parallel, chunk-aware; requires compatible chunks.
import dask.array as da
d1 = da.from_array(arr1, chunks=1)
d2 = da.from_array(arr2, chunks=1)
# Lazy stack along new axis
d_stacked = da.stack([d1, d2]) # shape (2, 2, 2)
print(d_stacked.compute())
# Lazy concatenate along axis=0
d_concat = da.concatenate([d1, d2], axis=0) # shape (4, 2)
print(d_concat.compute())
Real-world pattern: stacking time series channels or image batches for ML/training.
# Multiple time series: 3 sensors × 1000 time steps
ts1 = np.random.rand(1000)
ts2 = np.random.rand(1000)
ts3 = np.random.rand(1000)
# Stack to (3 channels, 1000 time) — channels-first
ts_stacked = np.stack([ts1, ts2, ts3], axis=0)
print(ts_stacked.shape) # (3, 1000)
# Or time-first (1000 time × 3 channels)
ts_time_first = np.stack([ts1, ts2, ts3], axis=1)
print(ts_time_first.shape) # (1000, 3)
# Dask version for large series
d_ts1 = da.from_array(ts1, chunks=100)
d_ts_stacked = da.stack([d_ts1, d_ts1*2, d_ts1*3], axis=0)
print(d_ts_stacked.compute().shape) # (3, 1000)
Best practices for stacking arrays. Use np.stack() for new axis — clearer intent than np.concatenate() + np.newaxis. Modern tip: use Polars .join() or xarray xr.concat()/xr.stack() — labeled stacking avoids manual axis management. Ensure compatible shapes — all arrays must match except stacked axis. Check chunk alignment in Dask — rechunk before stacking if needed. Use axis thoughtfully — 0 for samples/batches, -1 for features/channels. Add type hints — def stack_ts(arrs: list[np.ndarray[np.float64, (None,)]]) -> np.ndarray[np.float64, (None, None)]. Monitor memory — stacking adds dimension (no copy if views). Use np.ascontiguousarray — ensure C-order after stacking. Use xarray — xr.concat([da1, da2], dim='time') — preserves labels. Use Dask — da.stack()/da.concatenate() for lazy large arrays. Test stacking — assert stacked[0].equals(original1). Use np.vstack/np.hstack — convenience for 1D/2D vertical/horizontal. Use da.rechunk() — align chunks before stacking. Profile with timeit — compare stack vs manual loops.
Stacking arrays combines multiple arrays along new or existing axes — NumPy stack/concatenate, Dask lazy equivalents, axis control for correct order. In 2026, use np.stack for new axes, Polars/xarray for labeled stacking, Dask for scale, and verify shapes/chunks. Master stacking, and you’ll assemble time series, images, batches, or features efficiently and correctly.
Next time you need to combine arrays — stack them properly. It’s Python’s cleanest way to say: “Merge these sequences — add a new dimension or join along an existing one.”