NumPy and pandas basics
From lists to arrays
A Python list can hold anything. A NumPy array holds one type of number, tightly packed — and that tradeoff is what makes it fast.
1Learn the idea
Read
What a NumPy array actually is
A NumPy array (numpy.ndarray) stores a fixed type of number in one contiguous block of memory — no per-element type-checking, no scattered objects to chase down. This is exactly the same idea that lets a spreadsheet compute a column sum instantly even with thousands of rows: uniform data laid out predictably is much faster to process in bulk than a mixed bag of arbitrary objects.
import numpy as np
scores_list = [88, 92, 79, 95, 61] # plain Python list
scores = np.array(scores_list) # NumPy array
print(type(scores), scores.dtype) # ndarray, int64 (or similar)
The dtype (data type) is worth noticing — it's new information a plain list doesn't have. Every element in scores is the same type, which is precisely the constraint that unlocks speed.
Read
The tradeoff, stated plainly
| | Python list | NumPy array | |---|---|---| | Can mix types | Yes | No — one dtype per array | | Resize freely | Yes | Awkward — arrays are usually recreated, not resized | | Math across all elements | Manual loop | Built-in, vectorized (next page) | | Speed on large numeric data | Slow | Fast |
Neither is "better" in general — a list of mixed-type records (a name, a score, a flag) is still a perfectly reasonable Python list. NumPy arrays earn their keep specifically for numeric data you're going to compute across, which describes almost everything in machine learning: scores, pixel values, embeddings, weights.
Read
Why this matters before you ever train a model
Every model you'll train later — a decision tree, a neural network, anything in scikit-learn or PyTorch — expects its input as arrays (or pandas structures built on top of arrays), not plain Python lists. Getting comfortable with arrays now means the data-handling code in every future lab looks familiar rather than like new syntax to decode on top of a new algorithm.
Read
A first look at shape
Real datasets aren't just a single row of numbers — they're often a grid: many examples (rows), each with several features (columns). NumPy represents this as a 2D array, and its .shape attribute tells you the grid's dimensions directly:
grid = np.array([[88, 92], [79, 95], [61, 70]])
print(grid.shape) # (3, 2) — 3 rows, 2 columns
.shape becomes one of the first things you check whenever something goes wrong in a data pipeline — a surprising number of bugs in real ML code are simply a shape mismatch between what one step produced and what the next step expected.
Go deeper
Before you start
Why this matters
A plain Python list — [88, 92, 79] — is flexible: it can mix types, grow and shrink freely, and hold anything from numbers to strings to other lists. That flexibility has a cost. Each element in a Python list is a separate object living somewhere in memory, and doing math across the list means Python looping over each one, one at a time, checking its type as it goes. For five numbers, that overhead is invisible. For five million, it's the difference between a script that runs instantly and one that takes minutes.
Related lessons
Check your understanding
Page assessment
Answer from memory. Completion is saved from this evidence, not from opening the next page.
All responses are required.