Skip to main content
v2026.11,858 entries · CC-BY 4.0

NumPy roll: Circular Shifts in Python Arrays

Master numpy.roll for circular array shifting in Python. Explore syntax, multi-axis tuples, periodic boundary conditions, and comparisons with linear shifts.

Written and maintained by CASRAI Editorial Board

Last updated

What it is used for in research

In scientific computing and quantitative research, numpy.roll shifts (rolls) the elements of an array along one or more specified axes. Elements that roll beyond the last index wrap cyclically back to the first index, creating a circular shift without changing array dimensions or data types.

Research workflows utilize numpy.roll primarily for modeling physical systems and processing periodic signals:

  • Periodic boundary conditions (PBCs): In numerical simulations of crystal lattices, cellular automata, molecular dynamics, and 2D Ising spin models, particles at the boundary interact with particles on the opposing edge of the domain. Calling numpy.roll shifts spatial grids along coordinate axes, enabling vectorized neighbor evaluation on a torus without nested loops.
  • Phase alignment in cyclic time series: Experimental data collected over natural cycles—such as 24-hour circadian telemetry, diurnal atmospheric measurements, or rotating machinery vibration—often require phase shifting to align baseline troughs across experimental subjects.
  • Convolution and circular filtering: Digital signal processing (DSP) and image analysis pipelines use circular shifting to implement discrete circular convolution and frequency-domain filtering stencils. Researchers combining coordinate systems with NumPy meshgrid coordinate arrays often roll grids to center spatial filters on specific regions of interest.
  • Finite difference stencils on closed curves: In numerical fluid dynamics and wave mechanics on closed rings or periodic domains, rolling arrays provides symmetric forward and backward differences at interior and edge nodes simultaneously.

Install or access

The numpy.roll function is part of the core NumPy library (numpy) available from the official Python Package Index (PyPI). It requires Python 3.9 or higher and runs across Linux, macOS, and Windows.

Install or verify NumPy in your virtual environment using official package managers:

# Install NumPy via pip from PyPI
pip install numpy

# Alternatively, install NumPy via conda from conda-forge
conda install -c conda-forge numpy

In Python research scripts or Jupyter notebooks, import the package conventionally as np:

import numpy as np

# Verify installed NumPy version (NumPy 2.x or 1.x)
print(np.__version__)

Step-by-step task

This worked example demonstrates how to apply numpy.roll to one-dimensional experimental signals and two-dimensional simulation lattices using Python.

Step 1: Perform a circular shift on a 1D experimental signal

To shift a 1D sequence, pass the array and an integer shift. A positive shift moves values to higher indices (rightward), wrapping trailing values to the start. A negative shift moves values to lower indices (leftward).

import numpy as np

# 1D experimental signal (e.g., hourly readings across a 10-hour window)
signal = np.array([12, 15, 19, 24, 30, 28, 22, 17, 14, 11])

# Shift signal forward by 2 positions (positive shift)
rolled_forward = np.roll(signal, shift=2)
print("Shift +2:", rolled_forward)

# Shift signal backward by 2 positions (negative shift)
rolled_backward = np.roll(signal, shift=-2)
print("Shift -2:", rolled_backward)

Step 2: Roll a 2D simulation grid along specific axes

When working with matrices, passing an integer to axis isolates the circular shift to rows (axis=0) or columns (axis=1). When flattened representations are needed, analysts frequently utilize NumPy ravel array flattening before or after spatial manipulations.

# 3x4 grid representing spatial sensor measurements
grid = np.array([
    [10, 11, 12, 13],
    [20, 21, 22, 23],
    [30, 31, 32, 33]
])

# Roll rows downward by 1 along axis 0 (vertical shift)
grid_down = np.roll(grid, shift=1, axis=0)
print("Row roll (axis=0):
", grid_down)

# Roll columns rightward by 1 along axis 1 (horizontal shift)
grid_right = np.roll(grid, shift=1, axis=1)
print("Column roll (axis=1):
", grid_right)

Step 3: Roll multiple axes simultaneously using tuple parameters

For diagonal or multi-dimensional shifts in numerical simulations, provide a tuple of shifts and a matching tuple of axes. Each axis shifts independently by its corresponding value.

# Shift rows down by 1 (axis 0) and columns right by 2 (axis 1) simultaneously
grid_diagonal = np.roll(grid, shift=(1, 2), axis=(0, 1))
print("Simultaneous 2D roll (shift=(1, 2), axis=(0, 1)):
", grid_diagonal)

Step 4: Vectorized nearest-neighbor calculation with periodic boundary conditions

In an Ising model or cellular automaton lattice, periodic boundary conditions wrap opposite edges. Summing rolled versions of the lattice computes nearest neighbors across the entire domain without edge checks.

# 4x4 spin lattice (-1 down, +1 up)
np.random.seed(42)
lattice = np.random.choice([-1, 1], size=(4, 4))

# Evaluate 4-neighbor sum (North, South, East, West) with periodic boundaries
north = np.roll(lattice, shift=-1, axis=0)
south = np.roll(lattice, shift=1, axis=0)
west  = np.roll(lattice, shift=-1, axis=1)
east  = np.roll(lattice, shift=1, axis=1)

neighbor_sum = north + south + west + east
print("Original Lattice:
", lattice)
print("Periodic Neighbor Sum:
", neighbor_sum)

Output and how to read it

The return value of numpy.roll is an ndarray of identical shape and dtype as the input array. Inspecting the shifted outputs illustrates the circular wrapping mechanism:

# 1D Roll Output:
Original:       [12, 15, 19, 24, 30, 28, 22, 17, 14, 11]
Shift +2:       [14, 11, 12, 15, 19, 24, 30, 28, 22, 17]
# Reading note: Values 14 and 11 wrapped from the tail to the first two indices.

# 2D Row Roll Output (axis=0, shift=1):
Original:
[[10, 11, 12, 13],
 [20, 21, 22, 23],
 [30, 31, 32, 33]]

Rolled Downward:
[[30, 31, 32, 33],
 [10, 11, 12, 13],
 [20, 21, 22, 23]]
# Reading note: Row 2 ([30, 31, 32, 33]) moved to row 0; rows 0 and 1 shifted down.

When reading output from multi-axis shifts, verify that each dimension shifted by its designated offset. Because numpy.roll operates cyclically, shifting an axis of length N by N positions returns an identical array.

Troubleshooting

Researchers encountering unexpected behavior with numpy.roll should check for the following common issues:

1. Omitting the axis argument on multidimensional arrays

If axis=None (the default), NumPy flattens the array into a 1D vector before shifting, and then reshapes it back into the original dimensions. This causes values to roll across row boundaries into adjacent columns rather than shifting rows independently:

# Unintended flattening shift
matrix = np.array([[1, 2], [3, 4]])
result = np.roll(matrix, 1)  # axis is None by default!
# Output is [[4, 1], [2, 3]] instead of [[3, 4], [1, 2]]

Resolution: Always supply explicit axis=0, axis=1, or a tuple of axes when working with arrays of dimension 2 or greater.

2. Tuple length mismatch between shift and axis

Passing tuples of unequal length to shift and axis triggers a runtime error:

ValueError: shift and axis must have the same size

Resolution: Ensure len(shift) == len(axis) when passing tuples. Alternatively, pass a single integer for shift alongside a tuple for axis to apply the same shift distance to all target dimensions.

3. Data leakage in non-periodic linear time series

A frequent methodological error in time series analysis is attempting to calculate lagged differences using diff = x - np.roll(x, 1). Because np.roll wraps cyclically, the final observation x[-1] is subtracted from the first observation x[0], corrupting the first index with an invalid boundary difference.

Resolution: For non-periodic linear series where boundary values must become missing (NaN), use pandas rolling window methods or Series lag operations (Series.shift()). Alternatively, pad boundaries with NumPy pad (np.pad) or mask the boundary value explicitly:

# Safe lag difference with NaN boundary in NumPy
lagged = np.roll(signal.astype(float), 1)
lagged[0] = np.nan
diff = signal - lagged

4. Memory copy overhead on massive scientific datasets

Unlike array slicing or strided views (such as x[::-1]), numpy.roll always creates and returns a new memory copy of the array. In memory-constrained environments or high-resolution neuroimaging and climate models, rolling a 20 GB array consumes another 20 GB of RAM.

Resolution: For labeled, chunked multi-gigabyte datasets, consider Xarray labeled multidimensional arrays backed by Dask, which execute chunked rolls out-of-core without exhausting physical memory.

Free alternatives

Depending on data structure, boundary conditions, and performance requirements, researchers choose between circular rolls, linear shifts with padding, and GPU-accelerated operations. The table below compares free alternatives to numpy.roll.

Tool / Function Package / Library Shift Mechanism Boundary Handling Key Research Application
numpy.roll NumPy (Open source, BSD-3) Discrete integer shift on ndarray Circular wrap-around (periodic) Lattice models, periodic boundary simulations, cyclic telemetry alignment
scipy.ndimage.shift SciPy (Open source, BSD-3) Sub-pixel spline interpolation and discrete shift Configurable: constant (cval), reflect, nearest, wrap Image registration, microscopy sub-pixel alignment, signal interpolation
pandas.Series.shift pandas (Open source, BSD-3) Index/value lag and lead on tabular Series/DataFrames Fills boundaries with NaN or custom scalar Longitudinal panel data, econometrics, econometric regression lags
collections.deque.rotate Python Standard Library In-place pointer rotation on double-ended queue Circular wrap-around Sliding buffer management, real-time streaming data ingestion
torch.roll PyTorch (Open source, Apache-2.0) Tensor circular shift with GPU/CUDA acceleration Circular wrap-around (periodic) Neural network periodic layers, deep learning spatial feature shifting

FAQ

Does numpy.roll modify the array in place or return a copy?

numpy.roll always returns a new array containing a copy of the shifted data. It does not modify the original input array in place, nor does it return an array view. As a result, subsequent modifications to the rolled array do not affect the original array.

What happens when axis is not specified in numpy.roll?

When the axis parameter is omitted (defaulting to axis=None), numpy.roll flattens the multi-dimensional array into a 1D sequence, rolls the elements by the specified shift, and reshapes the sequence back to the original array shape. In most matrix workflows, this disrupts column and row alignment, so passing explicit axis indices is recommended.

Can numpy.roll accept negative shift values?

Yes. A positive integer shifts elements toward higher indices (forward / right / down), wrapping trailing items to the beginning. A negative integer shifts elements toward lower indices (backward / left / up), wrapping leading items to the end of the axis.

How do you roll elements along multiple dimensions at once?

To shift multiple dimensions simultaneously, pass a tuple of integers to shift and an equal-length tuple of axis indices to axis. For example, np.roll(grid, shift=(1, -2), axis=(0, 1)) shifts rows down by 1 and columns left by 2 in a single vectorized call.

How does numpy.roll differ from pandas shift?

numpy.roll performs a circular shift where values rolling off one end wrap around to the other end. In contrast, pandas.Series.shift performs a linear shift where values pushed past the boundary are dropped, and newly created positions at the start or end are filled with missing values (NaN) to prevent circular data contamination in time-series models.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about NumPy roll: Circular Shifts in Python Arrays

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →