Python NumPy
NumPy is the foundation of numerical Python. Its ndarray stores numbers in a compact block of memory and runs maths on whole arrays at once, which is far faster and shorter than looping over lists. Pandas, scikit-learn and Matplotlib are all built on it.
- Create arrays and inspect their shape
- Index, slice and filter with masks
- Vectorised maths and broadcasting
- Statistics along rows and columns
Install and import
python -m pip install numpyimport numpy as npprint(np.__version__.split(".")[0] >= "2")True
np is the standard alias; every NumPy example you find online uses it.
Create arrays
import numpy as np a = np.array([3, 1, 4, 1, 5])print(a, a.dtype, a.shape) m = np.array([[1, 2, 3], [4, 5, 6]])print(m)print(m.shape, m.ndim, m.size)[3 1 4 1 5] int64 (5,) [[1 2 3] [4 5 6]] (2, 3) 2 6
Helper functions build common arrays:
import numpy as np print(np.zeros(3), np.ones((2, 2), dtype=int).tolist())print(np.arange(0, 10, 2))print(np.linspace(0, 1, 5))print(np.eye(3, dtype=int))[0. 0. 0.] [[1, 1], [1, 1]] [0 2 4 6 8] [0. 0.25 0.5 0.75 1. ] [[1 0 0] [0 1 0] [0 0 1]]
Arrays vs lists
Maths on an array applies to every element. The same operator on a list does something else:
import numpy as np prices = [100, 250, 80]print(prices * 2) # list: repeated arr = np.array(prices)print(arr * 2) # array: every element doubledprint(arr * 1.18) # add 18% tax to allprint(arr + np.array([1, 2, 3])) # element-wise addition[100, 250, 80, 100, 250, 80] [200 500 160] [118. 295. 94.4] [101 252 83]
Reshape
import numpy as np a = np.arange(1, 13)grid = a.reshape(3, 4)print(grid)print(grid.T.shape) # transpose: 4 x 3print(grid.flatten()[:5])[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] (4, 3) [1 2 3 4 5]
Indexing and slicing
For 2-D arrays, use [row, column]:
import numpy as np g = np.arange(1, 13).reshape(3, 4)print(g[0, 0], g[2, -1])print(g[1]) # second rowprint(g[:, 1]) # second columnprint(g[0:2, 1:3]) # sub-grid1 12 [5 6 7 8] [ 2 6 10] [[2 3] [6 7]]
Boolean masks
A comparison gives an array of True/False values, which you can use to select elements:
import numpy as np scores = np.array([45, 82, 67, 91, 38, 74])mask = scores >= 60print(mask)print(scores[mask])print(scores[(scores > 50) & (scores < 80)]) # use & and |, not and/orprint(np.where(scores >= 60, "pass", "fail"))[False True True True False True] [82 67 91 74] [67 74] ['fail' 'pass' 'pass' 'pass' 'fail' 'pass']
Statistics
import numpy as np sales = np.array([[120, 90, 150], [80, 110, 95]]) # 2 stores x 3 monthsprint(sales.sum(), sales.mean().round(2))print(sales.sum(axis=0)) # per month (down the columns)print(sales.sum(axis=1)) # per store (across the rows)print(sales.max(), sales.argmax(), np.median(sales))645 107.5 [200 200 245] [360 285] 150 2 102.5
axis=0 means “collapse the rows” (one result per column) and axis=1 means “collapse the columns” (one result per row).
Broadcasting
When shapes differ, NumPy stretches the smaller array to fit, as long as the dimensions are compatible:
import numpy as np marks = np.array([[70, 80, 90], [60, 75, 85]])bonus = np.array([5, 0, 10]) # one bonus per subjectprint(marks + bonus)print(marks / marks.max(axis=1, keepdims=True)) # normalise each row[[ 75 80 100] [ 65 75 95]] [[0.77777778 0.88888889 1. ] [0.70588235 0.88235294 1. ]]
Random numbers
import numpy as np rng = np.random.default_rng(seed=42)print(rng.integers(1, 7, size=5)) # dice rollsprint(rng.random(3).round(3))print(rng.choice(["red", "green", "blue"], size=4))[1 5 4 3 3] [0.697 0.094 0.976] ['blue' 'blue' 'blue' 'blue']
A fixed seed makes the results repeatable, which is useful for tests.
Why NumPy is fast
import numpy as np, time n = 1_000_000numbers = list(range(n))arr = np.arange(n) t = time.perf_counter(); total_list = sum(x * x for x in numbers); list_time = time.perf_counter() - tt = time.perf_counter(); total_np = int((arr * arr).sum()); np_time = time.perf_counter() - t print(total_list == total_np)print("NumPy faster:", np_time < list_time)True NumPy faster: True
Check your understanding
Predict the output
import numpy as npa = np.array([[1, 2], [3, 4]])print(a * a, a.sum(axis=0), a[a > 2])[[ 1 4] [ 9 16]] [4 6] [3 4]
* multiplies element by element. sum(axis=0) adds down each column. The mask keeps the values greater than 2.
Quick quiz
1. What is np.array([1, 2, 3]) * 2?
Array maths is element-wise.
2. What does arr.shape return for a 3 x 4 array?
shape is a tuple of the size of each dimension.
3. Which combines two conditions in a mask?
Use &, | and ~ with brackets; and / or do not work element-wise.
Exercise: class report
Marks of 4 students in 3 subjects are in a 4 x 3 array. Print each student’s total, each subject’s average, and how many marks are below 40.
[[78, 65, 90], [35, 48, 52], [88, 92, 79], [40, 39, 61]]
Totals: [233 135 259 140] Subject averages: [60.25 61. 70.5 ] Marks below 40: 2
Hint 1
sum(axis=1) for students, mean(axis=0) for subjects.
import numpy as np marks = np.array([[78, 65, 90], [35, 48, 52], [88, 92, 79], [40, 39, 61]])print("Totals:", marks.sum(axis=1))print("Subject averages:", marks.mean(axis=0).round(2))print("Marks below 40:", (marks < 40).sum())Totals: [233 135 259 140] Subject averages: [60.25 61. 70.5 ] Marks below 40: 2
Summing a boolean array counts the True values, so (marks < 40).sum() counts failing marks without a loop.
Program Practice
100 Python NumPy Programs
Every program has a step-by-step explanation, colour-coded code and its real output.
NumPy FAQ
What is NumPy used for?
Fast numerical computing: arrays, linear algebra, statistics and random numbers. It is the base for pandas, SciPy, scikit-learn and most data and ML libraries.
What is the difference between a Python list and a NumPy array?
A NumPy array holds items of one type in contiguous memory and supports element-wise maths. A list can mix types and its operators mean concatenation and repetition.
What does axis=0 mean in NumPy?
It means “along the rows”, so the result has one value per column. axis=1 gives one value per row.
1 thought on “Python NumPy”