"If Python is the Swiss Army knife, NumPy is the power drill — built for speed when you need to crunch numbers at scale."
Learning Objectives
By the end of this module, you will be able to:
- Create and manipulate NumPy arrays (ndarrays) with confidence
- Select data using indexing, slicing, and boolean masking
- Apply broadcasting rules to perform operations on arrays of different shapes
- Leverage vectorized operations to replace slow Python loops
- Perform basic linear algebra and random number generation
- Explain why NumPy is dramatically faster than pure Python
Why NumPy?
Imagine summing a million salaries. A Python list is like counting coins by hand; NumPy is like dumping them on a scale. Arrays are homogeneous (one type per array) and packed in memory, so C-level loops can blast through them.
| Python list | NumPy ndarray |
|---|---|
| Mixed types allowed | One dtype per array |
| Pointer soup in memory | Contiguous block |
for loops for math | Whole-array ops in one call |
Fun Fact: Pandas columns are often backed by NumPy (or similar) arrays under the hood.
1. Creating Arrays
From Python Lists
Think 1D = single row of numbers, 2D = spreadsheet without column names. Attributes you’ll use constantly:
| Attribute | Meaning |
|---|---|
.shape | Tuple like (rows, cols) |
.dtype | int64, float64, etc. |
.ndim | Number of dimensions |
Built-in Array Generators
| Function | Plain English |
|---|---|
zeros, ones | Template grids filled with 0 or 1 |
arange | Like range, but returns an array |
linspace | Evenly spaced points (great for charts) |
eye | Identity matrix (diagonal of 1s) |
Try This! Create a 4×3 array of monthly placeholders with zeros and set one row to fake Q1 numbers.
2. Indexing and Slicing
1D Indexing
Same spirit as Python lists: [0], [-1], slicing [start:stop:step].
2D Indexing
Syntax is array[row, col] — row first, column second. A lone : means “everything along this axis.”
Boolean Indexing (Masking)
You build a True/False array the same shape as your data, then data[mask] keeps only True positions. It’s SQL WHERE without a database.
| Operation | Meaning |
|---|---|
arr > 60 | Mask of highs |
arr[mask] | Filtered values |
(a > 10) & (b < 5) | Combine with &, ` |
Fancy Indexing
Pick specific positions with an array of indices, or use np.where(condition, yes, no) to build labeled arrays.
Concept: Masks and fancy indexing avoid Python for loops — that’s where speed comes from.
3. Array Operations (Vectorization)
Arithmetic between same-shaped arrays is element-wise — multiply price × quantity without a loop.
Aggregations like .sum(), .mean(), .std() reduce the whole array or an axis (row-wise vs column-wise).
Universal Functions (ufuncs)
np.sqrt, np.log, np.round, np.cumsum, np.diff — each applies to every element in one shot.
Key Takeaway (section): If you’re writing for i in range(len(arr)), pause and look for a ufunc or slice.
4. Broadcasting
Broadcasting stretches smaller arrays (conceptually) so they match larger ones for arithmetic — e.g. multiply every row by a vector of store weights.
Rules (simplified): align shapes from the right; dimensions must match or one side must be 1. Otherwise NumPy raises a shape error.
| Shape A | Shape B | Result of A + B (conceptually) |
|---|---|---|
(5,) | (5,) | (5,) element-wise |
(4, 3) | (3,) | (4, 3) — row matrix + vector across columns |
(4, 1) | (1, 3) | (4, 3) — both directions stretch |
Try This! Subtract each column’s mean from that column to “center” a small matrix — notice you never wrote a nested loop.
Concept: When broadcasting errors strike, print .shape for every operand — the mismatch is almost always visible from the right edge inward.
5. Reshaping and Stacking
| Tool | What it does |
|---|---|
.reshape | Same data, new rows/cols (total size unchanged) |
.T | Swap rows and columns |
vstack / hstack | Glue arrays vertically or horizontally |
column_stack | Turn parallel 1D arrays into columns |
6. Linear Algebra Basics
A @ v (or np.dot) is matrix–vector multiply — weighted scores, rotations, regression-style operations all use this.
np.linalg.solve solves linear systems; eigen stuff shows up in PCA-style thinking later.
7. Random Number Generation
Use rng = np.random.default_rng(seed) for reproducible “dice rolls”: normal salaries, integer samples, shuffles. Same seed → same fake data → shareable examples.
8. Performance: NumPy vs Pure Python Benchmarks
Typical speedups for big arrays: tens to hundreds× on sum, multiply, and filter — because work happens in compiled code over contiguous memory.
Key Example: This pair shows why analysts reach for NumPy: the same work in Python vs one vectorized expression.
[object Object], numpy ,[object Object], np
revenue = np.array([,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],])
,[object Object],
strong = revenue[revenue > ,[object Object],]
pct_above = strong.mean() ,[object Object],
,[object Object],
prices = np.array([,[object Object],, ,[object Object],, ,[object Object],])
qty = np.array([,[object Object],, ,[object Object],, ,[object Object],])
line_total = (prices * qty).,[object Object],()NumPy habits for analysts
- Prefer
np.asarraywhen you accept array-likes but don’t need to copy. - Use
np.wherefor vectorized if/else instead of list comprehensions over scalars. - Name axes in comments when sharing
shape—(n_customers, n_months)beats “2D”. np.nanpropagates through aggregates:np.nansum,np.nanmeanwhen NaNs are expected.- Set
seedwhenever you share notebook outputs that include randomness.
Memory tip: float32 halves footprint vs float64; confirm precision is acceptable for money if regulatory rules exist.
Practice Exercises
Exercise 1: Sales Analysis (Beginner)
3 products × 12 months in a 2D array: total per product, best month index per product, highest average monthly sales.
Exercise 2: Grade Normalization (Intermediate)
Min–max normalize scores to 0–100 with vectorized ops.
Exercise 3: Monte Carlo Simulation (Intermediate)
Simulate many portfolio returns; estimate probability of positive return.
Exercise 4: Image as Array (Advanced)
Build a small grayscale array; draw border and diagonal; report mean brightness.
Exercise 5: Rolling Statistics (Advanced)
Implement rolling mean with slices or np.convolve.
Mini-Project: Portfolio Risk Analyzer
Simulate daily returns for several stocks, build random weight portfolios, and compare risk vs return. Use default_rng, @ for weights, and aggregations.
Key Takeaways
- Ndarrays are fast because they’re typed and contiguous.
- Vectorize before you loop; ufuncs and masks are your main tools.
- Broadcasting is powerful once shapes align from the right.
- Seeded
default_rngmakes simulations reproducible.
Resources for Further Learning
- NumPy Official Tutorial
- NumPy for Absolute Beginners
- From Python to NumPy (free online book)
- 100 NumPy Exercises — practice drills
- Visual Introduction to NumPy by Jay Alammar
Key Takeaway
- Treat numeric tables as ndarrays and think in rows, columns, and axes.
- Filter with boolean masks instead of Python loops whenever possible.
- Apply one operation to the whole array to stay in fast C code paths.
- Respect broadcasting rules so shapes line up from the right.
- Seed random generators so analyses and demos are reproducible.
Next up: Module 3 — Pandas: Data Manipulation Mastery — where NumPy arrays get labels, columns, and superpowers for real-world data.