Reshaping time series data: Getting the order correct! is critical in NumPy — the dimension order directly impacts performance, memory access patterns, vectorization efficiency, and compatibility with downstream operations (e.g., broadcasting, reductions, ML models, plotting). Wrong order can cause slow strided access, unnecessary copies, or incorrect results. In 2026, correct reshaping ensures C-contiguous arrays for speed, aligns with pandas/Polars/xarray conventions (time usually first or last), and optimizes chunking in Dask for parallel compute. Always think: “Which dimension do I operate on most?” — put it innermost (last) for best cache locality and vectorization.
Here’s a complete, practical guide to reshaping time series data with correct dimension order in NumPy: understanding C vs F order, choosing time-first vs time-last, reshaping/transposing examples, performance impact, real-world patterns, and modern best practices with type hints, memory views, pandas/Polars/xarray equivalents, and Dask integration.
NumPy memory layout & dimension order — C-contiguous (row-major, last dim varies fastest) vs F-contiguous (column-major, first dim varies fastest).
import numpy as np
# Time series: 10 days × 2 variables (time is outer)
data = np.array([
[1.2, 10.5], [2.3, 11.2], [3.4, 12.8], [4.5, 13.9], [5.6, 15.1],
[6.7, 16.4], [7.8, 17.7], [8.9, 18.9], [9.0, 20.1], [10.1, 21.3]
], order='C') # default C-order: rows contiguous
print(data.flags) # C_CONTIGUOUS: True
# Reshape to (2 variables, 10 time steps) — transpose
data_var_first = data.T # now variables × time
print(data_var_first.shape) # (2, 10)
print(data_var_first.flags) # F_CONTIGUOUS: True (transposed)
# Reshape to 3D: (variables, time, 1 obs per time) — common for ML (channels × time × 1)
reshaped = data_var_first[..., np.newaxis] # (2, 10, 1)
print(reshaped.shape)
Choosing order: time-first (time × features) vs time-last (features × time).
- Time-first (time × features) — natural for sequential models (LSTM/Transformer), chronological slicing, pandas
DatetimeIndex. Default in most time series libs. - Time-last (features × time) — better for vectorized ops on features (e.g., normalize across time), image-like processing, some CNNs. Common in signal processing.
Correct reshaping examples — preserve order and avoid copies.
# Original: time × variables (10 × 2)
# Goal: variables × time × 1 (2 × 10 × 1) for channels-first ML
reshaped = data.T[..., np.newaxis] # transpose + add dim (view)
print(reshaped.shape, reshaped.flags.c_contiguous) # (2, 10, 1) False
# Make contiguous if needed (copy)
contiguous = np.ascontiguousarray(reshaped)
print(contiguous.flags.c_contiguous) # True
# Alternative: reshape directly (but order matters!)
# Wrong order if you reshape without transpose first
wrong = data.reshape(2, 10, 1) # (2, 10, 1) but interleaved — wrong!
print(wrong[0, :, 0]) # [1.2 2.3 3.4 ...] — mixes variables!
Real-world pattern: reshape multi-variate time series for ML (channels-first LSTM) or visualization.
# Multi-variate: time × 3 features
data_multi = np.random.rand(365, 3) # 1 year × temp/humidity/pressure
# Reshape to (features, time, 1) for channels-first
ml_ready = data_multi.T[..., np.newaxis] # (3, 365, 1)
print(ml_ready.shape)
# Or to (time, features) for pandas
df = pd.DataFrame(data_multi, index=dates, columns=['temp', 'hum', 'press'])
print(df.head())
Best practices for correct reshaping of time series. Prefer time-first (time × features) — aligns with pandas, Polars, xarray, and sequential models. Modern tip: use Polars .pivot()/.melt() or xarray .transpose() — labeled reshaping avoids manual order errors. Use views — reshape/transpose return views (no copy). Use np.ascontiguousarray — force C-order before heavy ops. Add type hints — def reshape_ts(arr: np.ndarray[np.float64, (None, None)]) -> np.ndarray[np.float64, (None, None, None)]. Monitor memory — arr.nbytes before/after reshape. Use np.newaxis — add singleton dimensions safely. Use np.rollaxis/np.swapaxes — alternative axis manipulation. Use xarray — da.transpose('time', 'variable') with labels. Use Dask arrays — da.reshape()/.transpose() for out-of-core. Test reshaping — assert reshaped.ravel().equals(original.ravel()). Profile with timeit — compare reshape vs manual loops. Use order='C'/'F' — control layout explicitly.
Reshaping time series data correctly ensures efficient access and computation — time-first for sequential models, time-last for vectorized feature ops. In 2026, use NumPy views, Polars/xarray for labeled reshaping, Dask for scale, and always verify order with ravel() equality. Master reshaping, and you’ll prepare time series for any analysis or model with speed and clarity.
Next time your time series needs reshaping — get the order right. It’s Python’s cleanest way to say: “Rearrange my temporal data — keep it efficient and correct.”