pythonforbio.
[WASM idle]
Library Overview03/06

NumPy

Starting sandbox…
Beginnerlesson

NumPy

In one line: a fixed-size, homogeneously-typed n-dimensional array plus compiled elementwise math over it.

Version at time of writing: 2.5.x · import numpy as np · Python 3.12–3.14

The mental model

A NumPy array is one contiguous block of memory plus three pieces of metadata: a shape, a dtype, and strides (how many bytes to step to move one element along each axis). Everything NumPy does — reshaping, transposing, slicing, broadcasting — is either arithmetic on that metadata (free, no copy) or a compiled loop over the buffer (fast).

Once you hold that picture, the behaviours that feel arbitrary stop being arbitrary:

  • arr.T is instant on a 10 GB array because it only swaps strides — Memory Layout and Strides
  • arr[1:5] shares memory with arr but arr1,2,3 does not — Views vs Copies
  • adding a (3,1) array to a (1,4) array gives (3,4) without allocating either operand — Broadcasting
  • appending to an array is expensive, because "fixed-size" is not negotiable

Why bioinformatics cares

Nearly every quantitative bio object is a matrix: an expression matrix (genes × samples), a distance matrix, a position weight matrix, a coverage vector, a genotype matrix. NumPy is where those live, and a per-element Python loop over a 20,000 × 500 matrix is ~10 million interpreter round-trips versus one compiled pass.

Biopython returns NumPy arrays in several places (Bio.motifs PWMs, Bio.PDB atom coordinates, alignment substitution counts), and pandas is NumPy underneath. You cannot skip this layer.

Core notes

The object ndarray · NumPy dtypes · Array Creation

Getting data out Indexing and Slicing · Boolean Masking · Fancy Indexing · Views vs Copies

Doing math Broadcasting · ufuncs · Vectorization · Axes and Reductions

Changing shape Reshaping and Stacking · Memory Layout and Strides

Specialised Structured Arrays · NumPy Random Generator · Linear Algebra with NumPy · Missing Data in NumPy · NumPy File IO

Applied

Applied - Expression Matrices with NumPy · Applied - Sequence Composition Analysis · Applied - Multiple Sequence Alignment Analysis

Install and check

pip install "numpy>=2.4,<3"
python -c "import numpy as np; print(np.__version__); np.show_config()"

np.show_config() tells you which BLAS you are linked against — relevant if matrix multiplication is unexpectedly slow.

The 20% that gets 80% of the work done

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])   # shape (2, 3)

a.shape, a.dtype, a.ndim, a.size
a.mean(axis=0)          # column means → shape (3,)
a.sum(axis=1)           # row sums     → shape (2,)
a[a > 3]                # boolean mask → 1-D
a[:, None]              # add an axis  → shape (2, 3, 1)... see broadcasting
np.where(a > 3, a, 0)   # vectorised if/else
np.log2(a + 1)          # ufunc, elementwise
a @ a.T                 # matrix multiply

What NumPy is not for

  • Labelled data → Pandas
  • Ragged / variable-length rows → lists, or an awkward-array style library
  • Mostly-zero matricesscipy.sparse (single-cell count matrices are >90% zero; a dense NumPy array will exhaust your RAM)
  • Data larger than memory → Dask, Zarr, or chunked reading

Gotchas that bite newcomers

  • Integer arrays overflow silently. np.int8(127) + 1 == -128. Read counts in int32 can overflow on large studies.
  • arr == np.nan is always False. Use np.isnan. See Missing Data in NumPy.
  • Modifying a slice modifies the original. See Views vs Copies.
  • Floating-point equality: use np.isclose / np.allclose, never ==.
  • NumPy 2 changed scalar promotion (NEP 50) — np.float32(1) + 1.0 stays float32 now. See Versions and Compatibility.

See also

Pandas · Ecosystem Map · Learning Path

lesson example

No output yet — run the code to populate this drawer.

MatplotlibPandas