Arrays & creation

The NumPy array (ndarray) is the foundation of the whole Python data stack. Pandas, scikit-learn, PyTorch and Matplotlib all hold their numbers in arrays, so learning to create and inspect them well pays off everywhere.

Creating arrays

import numpy as np

a = np.array([1, 2, 3])
m = np.array([[1, 2], [3, 4]])
zeros = np.zeros((3, 4))
seq = np.arange(0, 10, 2)        # [0 2 4 6 8]
lin = np.linspace(0, 1, 5)       # 5 evenly spaced numbers

print(m.shape, m.ndim, m.dtype)  # (2, 2) 2 int64

NumPy arrays are homogeneous and stored contiguously, which makes maths on them 10–100x faster than Python lists.

The main constructors

Call Gives you
np.zeros(n) / np.ones((r, c)) Arrays filled with 0 or 1
np.full((2, 3), 9.5) Every element set to one value
np.empty((3, 3)) Uninitialised memory — fast, but contains garbage
np.arange(start, stop, step) Like range, with a step and an exclusive stop
np.linspace(start, stop, num) A fixed count of evenly spaced values, stop included
np.eye(3) Identity matrix
np.zeros_like(x) Same shape and dtype as x, filled with zeros

Use arange when the step matters (every 5 minutes) and linspace when the number of points matters (100 points for a smooth curve). arange with float steps can produce one element more or fewer than you expect because of floating-point rounding, so prefer linspace for decimals.

The attributes worth memorising

stock = np.array([[12, 4, 9],       # 2 warehouses x 3 products
                  [ 7, 0, 15]])

stock.shape      # (2, 3)  rows, columns
stock.ndim       # 2       number of dimensions
stock.size       # 6       total elements
stock.dtype      # int64   type of every element
stock.nbytes     # 48      memory used

shape is the one you will print most often. Most NumPy bugs are shape bugs.

Generating data

rng = np.random.default_rng(42)
prices = rng.normal(250, 40, size=1000).round(2)   # simulated item prices in ₹
codes = rng.integers(1, 5, size=10)                # store codes 1..4

Seeding with default_rng(42) makes the numbers reproducible, which matters when you share a notebook.

Why not just use a list?

py_list = list(range(1_000_000))
arr = np.arange(1_000_000)

# lists need a loop or comprehension
doubled_list = [x * 2 for x in py_list]
# arrays do it in compiled code
doubled_arr = arr * 2

The array version is typically 20–50x faster and uses roughly a quarter of the memory, because a Python list stores pointers to a million separate integer objects while the array stores a million packed 8-byte values.

Loading from files

data = np.loadtxt("readings.csv", delimiter=",", skiprows=1)
np.save("readings.npy", data)      # fast binary round-trip
back = np.load("readings.npy")

For anything with mixed text and numbers or column names, reach for pandas instead.

Common mistakes

  • np.array(1, 2, 3) — the values must be in a list: np.array([1, 2, 3]).
  • Expecting np.arange(0, 1, 0.1) to include 1.0; the stop is exclusive.
  • Using np.empty and assuming it is zero-filled.
  • Building an array by appending in a loop; np.append copies the whole array each time. Collect into a list and convert once, or preallocate with np.zeros.

Practice

Create a 4 x 6 array of weekly sales for four branches (use a seeded Generator, values between 20,000 and 80,000). Print its shape, dtype and memory use, build a matching all-zeros array with zeros_like, and make a linspace of 6 target values rising from 40,000 to 70,000.

B

Written by Bablu Kumar Jha

Founder, BeeProton AI · Mumbai, Maharashtra, India