Arrays with NumPy
NumPy is not part of Python itself — it is a library, imported by
convention as np:
import numpy as np
If it is missing, install it once: pip install numpy.
Creating arrays
a = np.array([1, 2, 3, 4])
b = np.zeros(5) # [0. 0. 0. 0. 0.]
c = np.ones(3) # [1. 1. 1.]
d = np.arange(0, 10, 2) # [0 2 4 6 8] like range()
e = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ]
m = np.array([[1, 2], [3, 4]]) # 2-D
arange behaves like range — stop excluded. linspace is different:
it gives you n evenly spaced values including both ends.
a.shape # (4,) dimensions
a.dtype # dtype('int64') all elements one type
a.size # 4
m.shape # (2, 2)
The key difference: element-wise operations
This is the whole reason NumPy exists.
lst = [1, 2, 3]
arr = np.array([1, 2, 3])
lst * 2 # [1, 2, 3, 1, 2, 3] repeats the list
arr * 2 # array([2, 4, 6]) multiplies each element
lst + lst # [1, 2, 3, 1, 2, 3] concatenates
arr + arr # array([2, 4, 6]) adds element-wise
The same operators mean different things for lists and arrays. That catches people constantly, and it is exactly the sort of thing an exam question tests.
With a list you would need a loop:
doubled = []
for x in lst:
doubled.append(x * 2)
doubled = arr * 2 # NumPy: one expression, no loop
More element-wise work
marks = np.array([78, 92, 65, 88])
marks + 5 # array([83, 97, 70, 93]) scaled up
marks / 100 # array([0.78, 0.92, 0.65, 0.88])
marks ** 2 # each squared
np.sqrt(marks) # square root of each
marks.sum() # 323
marks.mean() # 80.75
marks.max() # 92
marks.std() # standard deviation
np.sqrt on an array does what math.sqrt cannot — math.sqrt takes one
number, np.sqrt takes the whole array at once.
Boolean indexing
Genuinely useful and worth knowing:
marks > 80 # array([False, True, False, True])
marks[marks > 80] # array([92, 88]) only those above 80
(marks > 80).sum() # 2 how many
marks[marks < 50] = 0 # set all fails to 0
(marks > 80).sum() works because True counts as 1 — the same
truthiness idea from the selection topic.
Arrays versus lists
| List | NumPy array | |
|---|---|---|
| Types | Mixed allowed | All one type |
| Size | Grows and shrinks | Fixed at creation |
* 2 | Repeats | Multiplies each element |
| Arithmetic | Needs a loop | Element-wise, no loop |
| Speed on numbers | Slower | Much faster |
| Part of Python | Yes | Library |
Use a list for general collections, mixed types, or anything that grows. Use an array for numeric data of fixed size where you want arithmetic across all of it.
2-D arrays
m = np.array([[1, 2, 3],
[4, 5, 6]])
m[0, 1] # 2 row 0, column 1
m[1] # array([4, 5, 6]) whole row
m[:, 0] # array([1, 4]) whole column
m.shape # (2, 3)
m.sum(axis=0) # array([5, 7, 9]) column sums
m.sum(axis=1) # array([6, 15]) row sums
m[0, 1] is the array way; a list of lists would need m[0][1].