KTU S1

Arrays with NumPy

By the end you should be able to: Create NumPy arrays, apply element-wise operations, and explain how an array differs from a Python list and when each is appropriate.

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

ListNumPy array
TypesMixed allowedAll one type
SizeGrows and shrinksFixed at creation
* 2RepeatsMultiplies each element
ArithmeticNeeds a loopElement-wise, no loop
Speed on numbersSlowerMuch faster
Part of PythonYesLibrary

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].