Skip to main content

named-arrays

tests codecov Ruff Documentation Status PyPI version DOI

named-arrays is an implementation of a named tensor, which assigns a name to each axis of an n-dimensional array such as a numpy array.

With a bare numpy array, the meaning of each axis lives in the programmer's head, and combining two arrays usually means inserting singleton dimensions until their shapes line up. Naming the axes removes both problems: arrays broadcast against each other by matching names, so a singleton dimension is never needed, and an operation such as a mean along the wavelength axis says exactly that.

named-arrays provides a very unapologetic implementation of a named tensor, since axes can only be accessed using their names, unlike xarray which allows for both name and index. Support for astropy.units is built in, so the values inside an array can carry a physical unit.

Installation

named-arrays is available on PyPI and can be installed using pip

pip install named-arrays

Features

The array types form a hierarchy, from a plain named tensor up to a discrete function of several variables.

Several modules extend these types to other libraries: na.plt for matplotlib, na.random and na.stats for sampling and statistics, na.regridding for resampling curvilinear grids, na.optimize for root finding and minimization, and na.transformations for rotations and translations.

Key concepts

The shape is a dictionary. shape maps each axis name to its length, and there is no positional equivalent. Anywhere the numpy API takes an axis=0, this library takes an axis="detector_x".

Arrays broadcast by matching names. Two arrays combine along the axes whose names they share, and the axes unique to either one are added to the result. An array of shape {"x": 3} plus an array of shape {"y": 2} therefore has shape {"x": 3, "y": 2}, with no reshaping and no singleton dimensions. Adding a new dimension to a calculation is a matter of giving an input an extra named axis.

Arrays are explicit or implicit. An explicit array such as ScalarArray stores its values. An implicit array such as ScalarLinearSpace stores the arguments that define it, so start, stop, and num remain available long after the array is created. Implicit arrays work in every operation an explicit array does, and .explicit materializes one on demand.

Most of the numpy API already works. These arrays implement the __array_function__ and __array_ufunc__ protocols, so np.mean, np.sqrt, and most of their siblings accept them directly, using axis names. Operations that numpy cannot express are defined in the named_arrays namespace instead.

Documentation

The full documentation, including the API reference, tutorials, and executable versions of the examples below, is hosted at named-arrays.readthedocs.io.

Examples

Broadcasting by name

The fundamental type is the ScalarArray, a composition of a numpy ndarray-like object and a tuple of axis names, which must have the same length as the number of dimensions in the array.

import numpy as np
import named_arrays as na

a = na.ScalarArray(np.array([1, 2, 3]), axes=("x",))
b = na.ScalarArray(np.array([4, 5]), axes=("y",))

Since the two arrays have different axis names, adding them together broadcasts them against each other automatically.

c = a + b
ScalarArray(
    ndarray=[[5, 6],
             [6, 7],
             [7, 8]],
    shape={'x': 3, 'y': 2},
)

The result is two-dimensional, and its shape is a dictionary.

c.shape
{'x': 3, 'y': 2}

All the usual numpy reduction operations take the name of the axis to remove.

c.mean("x")
ScalarArray(
    ndarray=[6., 7.],
    shape={'y': 2},
)

To index the array, use a dictionary with the axis names as the keys, so the meaning of an index does not depend on the order of the axes.

c[dict(x=0)]
ScalarArray(
    ndarray=[5, 6],
    shape={'y': 2},
)

Implicit arrays

We recommend that you rarely create instances of ScalarArray directly. Instead, use the implicit array classes ScalarLinearSpace, ScalarLogarithmicSpace, and ScalarGeometricSpace, which mirror numpy.linspace(), numpy.logspace(), and numpy.geomspace(), with the advantage of remembering the arguments used to define them.

d = na.ScalarLinearSpace(0, 1, axis="z", num=4)
ScalarLinearSpace(start=0, stop=1, axis='z', num=4, endpoint=True, centers=False)

These implicit classes work just like a ScalarArray in any operation, and .explicit materializes one on demand.

a + d
ScalarArray(
    ndarray=[[1.        , 1.33333333, 1.66666667, 2.        ],
             [2.        , 2.33333333, 2.66666667, 3.        ],
             [3.        , 3.33333333, 3.66666667, 4.        ]],
    shape={'x': 3, 'z': 4},
)

One extra axis, one plotting call

An extra named axis costs nothing, so a family of curves is a single array, and one plotting call draws all of them.

import astropy.units as u
import matplotlib.pyplot as plt

# Define the independent variable
x = na.linspace(0, 2 * np.pi, axis="x", num=101) * u.rad

# Add an axis representing three different amplitudes
amplitude = na.ScalarArray(np.array([1, 2, 3]), axes=("amplitude",))

# The result has both axes, without any reshaping
y = amplitude * np.sin(x)

fig, ax = plt.subplots(constrained_layout=True);
na.plt.plot(x, y, axis="x", ax=ax);
ax.set_xlabel(f"angle ({x.unit:latex_inline})");
ax.set_ylabel("amplitude");

plot

Uncertainty propagation

An UncertainScalarArray carries a distribution alongside its nominal value, and every operation propagates it, so the error bar at the end of a calculation needs no separate bookkeeping.

# Define a radius known to about 5%
radius = na.NormalUncertainScalarArray(
    nominal=10 * u.cm,
    width=0.5 * u.cm,
    num_distribution=11,
)

# Compute the area of the corresponding circle
area = np.pi * np.square(radius)

# The uncertainty in the radius is carried into the area
area.nominal, np.std(area.distribution, axis="_distribution")

Citation

If you use named-arrays in your research, please cite it. The citation metadata is kept in CITATION.cff, which the "Cite this repository" button on GitHub can export as BibTeX or APA.

Every release of named-arrays is archived on Zenodo with its own DOI. The concept DOI, 10.5281/zenodo.23072813, always resolves to the latest version, and the Zenodo page lists the DOI of every version. Please include the version of named-arrays that you used, which is given by importlib.metadata.version("named-arrays"). The BibTeX entry below uses the concept DOI. To cite a specific version instead, replace doi with the DOI of that version.

@software{named-arrays,
  author = {Smart, Roy T. and Parker, Jacob D.},
  title = {named-arrays},
  version = {X.Y.Z},
  doi = {10.5281/zenodo.23072813},
  url = {https://github.com/sun-data/named-arrays},
}

Development

Install the package in editable mode along with its test dependencies, and run the test suite using pytest:

pip install -e .[test]
pytest

The suite is large, so continuous integration spreads it over every available core using pytest-xdist. To do the same locally:

pytest -n auto

This project is linted using ruff, which is checked by continuous integration:

ruff check .

To build the documentation locally:

pip install -e .[doc]
sphinx-build docs docs/_build/html

Metadata

Release files for named-arrays 2.12.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for named-arrays 2.12.1
File Size Uploaded
named_arrays-2.12.1.tar.gz 328.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for named-arrays 2.12.1
File Interpreter ABI Platform
named_arrays-2.12.1-py3-none-any.whl Python 3 none any Details

Total release size: 657.1 kB

Release files / named_arrays-2.12.1.tar.gz

Download URL named_arrays-2.12.1.tar.gz
Size 328.1 kB
Tags Source
SHA-256 checksum
How to use checksums
81c5ad555c2526d1ce850a464c773a66bb6c4c54a073c88e8d8dcc56a56ac4a4
BLAKE2b-256 checksum
How to use checksums
09be0327fdc435f74e0f9f5238d4de33d34c1a0560c378f92ef20eb685e1156a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / named_arrays-2.12.1-py3-none-any.whl

Download URL named_arrays-2.12.1-py3-none-any.whl
Size 328.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b5abcedfb0d07b42497a4dae0e41c4a451ff9f4f10193fcc40c8008300bc6e6
BLAKE2b-256 checksum
How to use checksums
d23d8c10304f69653fed555fc7f22b31fb8d5fa19a98d0dbd3b7cb6d782fd56f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

2.15.0

2 release files

This release

2.12.1 This release

2 release files

2.11.0

2 release files

2.9.0

2 release files

2.8.0

2 release files

2.7.0

2 release files

2.6.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.27.1

2 release files

0.27.0

2 release files

0.26.0

2 release files

0.25.1

2 release files

0.25.0

2 release files

0.24.0

2 release files

0.23.0

2 release files

0.22.0

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.18.2

2 release files

0.18.1

2 release files

0.18.0

2 release files

0.17.1

2 release files

0.17.0

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page