NumPy
01 / 03

Arrays, Data Types & Creation

NumPy: Arrays, Data Types & Creation

NumPy is the foundation of the Python scientific computing ecosystem. Its ndarray stores homogeneous data in a contiguous memory block — operations are implemented in C and 10–100× faster than pure Python loops.

Installation & Import

pip install numpy
import numpy as np

np.__version__   # '2.0.0'

Creating Arrays

# From Python lists
a = np.array([1, 2, 3])                      # 1D, shape (3,)
b = np.array([[1, 2, 3], [4, 5, 6]])         # 2D, shape (2, 3)
c = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])  # 3D, shape (2, 2, 2)

# Built-in creators
np.zeros((3, 4))             # 3×4 array of 0.0
np.ones((2, 3))              # 2×3 array of 1.0
np.full((2, 3), 7)           # 2×3 array of 7
np.eye(4)                    # 4×4 identity matrix
np.empty((3, 3))             # uninitialized (garbage values, faster)

# Ranges
np.arange(0, 10, 2)          # [0, 2, 4, 6, 8]  (like range, but returns array)
np.linspace(0, 1, 5)         # [0.0, 0.25, 0.5, 0.75, 1.0]  (evenly spaced)
np.logspace(0, 2, 3)         # [1, 10, 100]  (log-spaced)

# Random arrays
rng = np.random.default_rng(seed=42)   # recommended: new-style Generator
rng.random((3, 3))           # uniform [0, 1)
rng.integers(0, 10, size=(3, 3))  # integers [0, 10)
rng.normal(0, 1, size=(100,))    # standard normal distribution
rng.choice([1, 2, 3, 4, 5], size=3, replace=False)  # random sample

# From other sources
np.fromfunction(lambda i, j: i * j, (4, 4))   # computed by function
np.frombuffer(buffer, dtype=np.uint8)          # from bytes
np.load('array.npy')                           # load from file
np.loadtxt('data.csv', delimiter=',', skiprows=1)

Data Types (dtype)

# Specify dtype at creation
np.array([1, 2, 3], dtype=np.float32)
np.zeros((3, 3), dtype=np.int8)
np.ones((2, 2), dtype=np.complex128)

# Common dtypes
np.int8, np.int16, np.int32, np.int64       # signed integers (8/16/32/64-bit)
np.uint8, np.uint16, np.uint32, np.uint64   # unsigned integers
np.float16, np.float32, np.float64          # floating point (float64 = double)
np.complex64, np.complex128                  # complex numbers
np.bool_                                     # boolean
np.str_, np.bytes_                           # string types

# Check and convert
a.dtype                # dtype('float64')
a.astype(np.int32)     # convert (returns new array)
a.view(np.uint8)       # reinterpret bytes (no copy)

# Structured arrays (like records)
dt = np.dtype([('name', 'U20'), ('age', np.int32), ('score', np.float64)])
records = np.array([('Alice', 30, 95.5), ('Bob', 25, 87.3)], dtype=dt)
records['name']        # array(['Alice', 'Bob'])
records['score']       # array([95.5, 87.3])

Array Properties

a = np.zeros((3, 4, 5))

a.shape        # (3, 4, 5)
a.ndim         # 3  — number of dimensions
a.size         # 60 — total number of elements
a.dtype        # dtype('float64')
a.itemsize     # 8  — bytes per element
a.nbytes       # 480 — total bytes (size * itemsize)

# Reshape (must keep same total elements)
a = np.arange(12)       # shape (12,)
b = a.reshape(3, 4)     # shape (3, 4)
c = a.reshape(2, -1)    # -1 inferred: shape (2, 6)
d = a.reshape(2, 2, 3)  # 3D: shape (2, 2, 3)
e = a.flatten()         # always returns copy, shape (12,)
f = a.ravel()           # returns view when possible, shape (12,)

# Transpose
b.T                     # shape (4, 3)
np.transpose(b)         # same
a.swapaxes(0, 2)        # swap axes

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free