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.
In the wild
See how this idea shows up as a product and a company — then come back to the lesson. Skills transfer across vendors.