NumPy Arrays Explained Simply

A list built for math

Advanced 13 min

In this lesson

The first of the three libraries. NumPy exists for one reason: doing math to a lot of numbers at once, quickly and in very little code.

Nearly everything else in data Python is built on top of it (pandas stores its columns as NumPy arrays), so half an hour here makes the next two lessons much easier.

Explain it like I’m 5

A NumPy array is a list built for math. Instead of visiting each number in turn, you do one operation to all of them at once.

The loop you stop writing

To add tax to every price in a list, you loop. With an array, you multiply the whole thing, and the loop disappears.

That is called a vectorized operation: one instruction applied to every element. It is shorter to read, and much faster, because the looping happens in compiled code rather than in Python.

Example
import numpy as np

prices_list = [1.20, 2.50, 0.60, 1.80]

# The Python way: a loop, or a comprehension.
with_tax_loop = [price * 1.2 for price in prices_list]

# The NumPy way: one operation, applied to everything.
prices = np.array(prices_list)
with_tax = prices * 1.2

print("list :", [round(p, 2) for p in with_tax_loop])
print("array:", with_tax.round(2))
print("same answer:", np.allclose(with_tax_loop, with_tax))
Output
list : [1.44, 3.0, 0.72, 2.16]
array: [1.44 3.   0.72 2.16]
same answer: True
Same answer. One of them scales to a million numbers.

Shape, slicing, and quick statistics

An array's shape is how many items it has along each dimension. A plain row of six numbers has shape (6,). A table of 3 rows and 4 columns has shape (3, 4). You will spend real time reading shapes, because most NumPy errors are shape errors.

Arrays also carry their own statistics (.mean(), .max(), .sum()) and can be filtered with a condition, which is the idea pandas builds on directly.

Example
import numpy as np

temps = np.array([12, 15, 19, 22, 17, 14])

print("values:", temps)
print("shape: ", temps.shape)
print("mean:  ", temps.mean())
print("max:   ", temps.max())
print("first three:", temps[:3])
print("above 15:   ", temps[temps > 15])
Output
values: [12 15 19 22 17 14]
shape:  (6,)
mean:   16.5
max:    22
first three: [12 15 19]
above 15:    [19 22 17]
Slicing works like a list. Filtering by a condition does not.

When shapes do not line up

Arithmetic between two arrays happens element by element, which requires their shapes to be compatible. When they are not, NumPy refuses rather than guessing, and the error message tells you both shapes, which is usually enough to spot the mistake.

Example
import numpy as np

a = np.array([1, 2, 3])
b = np.array([10, 20])

try:
    print(a + b)
except ValueError as err:
    print("ValueError:", str(err).strip())
Output
ValueError: operands could not be broadcast together with shapes (3,) (2,)
Three numbers plus two numbers is not a question with an answer.

When not to reach for NumPy

NumPy is for numbers, all of the same type. That is the source of its speed and also its limit.

For a handful of values, a plain list is simpler and the speed difference is irrelevant. For rows mixing names, dates, and categories, an array is the wrong shape of tool entirely. That is what pandas is for, and it is the next lesson. Reach for NumPy when you have a lot of numbers and want to do math to all of them.

Convert a whole array of temperatures from Celsius to Fahrenheit in one expression. The formula is C × 9 / 5 + 32. Write it once, applied to the entire array, with no loop.

import numpy as np

celsius = np.array([0, 12, 21, 30, 37])

# TODO: convert every value at once, no loop
fahrenheit = celsius

print("celsius:   ", celsius)
print("fahrenheit:", fahrenheit)
print("warmest F: ", fahrenheit.max())

Common mistake: Expecting list math and array math to match

Why it happens:

They look identical, and both are sequences of numbers.

How to fix it:

On a list, * repeats and + joins. On an array they do arithmetic to every element. Convert with np.array(...) first.

Common mistake: Ignoring the shape in an error message

Why it happens:

“could not be broadcast together” reads like something deep is wrong.

How to fix it:

The two shapes are printed right there. Compare them, and print .shape on both arrays.

Common mistake: Using arrays for mixed text-and-number data

Why it happens:

NumPy accepts it without complaint, so it looks supported.

How to fix it:

Mixed types force everything to text and you lose the math. Use a pandas DataFrame for tables with names, dates, or categories.

Common mistake: Reaching for NumPy for five numbers

Why it happens:

It is the new tool, so it feels like the better one.

How to fix it:

The speed only matters in bulk. A short list plus sum() is clearer for small jobs.

What does vectorized mean?

What does an array's shape describe?

What does temps[temps > 15] give you?

Mini exercise (medium)

A week of rainfall readings in millimeters. Using array operations rather than loops, find the total rainfall, how many days were completely dry, the wettest day's reading, and every reading above the week's average.

Take the wheel. Complete the code, hit Run, and check your output right here.

import numpy as np

rainfall = np.array([2.0, 0.0, 5.5, 1.2, 0.0, 8.1, 3.3])

total = 0          # TODO: total rainfall for the week
dry_days = 0       # TODO: how many days recorded exactly 0
wettest = 0        # TODO: the largest single reading
above_average = np.array([])   # TODO: every reading above the week's mean

print("total mm:      ", round(float(total), 1))
print("dry days:      ", int(dry_days))
print("wettest day mm:", round(float(wettest), 1))
print("above average: ", above_average)

What to learn next

You met the array: vectorized arithmetic with no loop, shape as the thing to check when something breaks, slicing that works like a list, and boolean indexing (temps[temps > 15]), which is the mechanism behind every filter you are about to write. You also saw where arrays stop being the right tool.

That limit is the next lesson. Real tables mix names, dates and categories with their numbers, and Pandas DataFrames is the tool built for exactly that.