NumPy Mastery: Arrays, Operations & Real Data Projects

Complete guide to NumPy covering array creation, indexing, slicing, arithmetic operations, broadcasting, matrix operations, and practical exercises including Sudoku validation and student data analysis.

Getting Started: Notebooks & Setup

What is a Jupyter Notebook

A Jupyter Notebook is a special file (.ipynb) that lets you write code, run it, and see output in one place. Unlike Python files, notebooks support markdown text, equations, images, and charts—making them ideal for data visualization and analysis workflows.

Three Ways to Use Notebooks

You can use Jupyter Notebooks via: (1) Anaconda Distribution with Jupyter Notebook installed locally, (2) VS Code with Jupyter extension, or (3) Google Colab (cloud-based with free GPU support). Each has trade-offs between ease of setup and available resources.

Key Notebook Settings

Enable auto-completion in settings to get function suggestions while typing. Enable auto-close brackets to avoid syntax errors. These settings are essential because NumPy has thousands of functions you won't remember.

NumPy Origin & Why It Matters

NumPy's Evolution

NumPy was created in 2005 by Travis Oliphant by combining two earlier libraries: Numeric (created 1995) and Numarray. This unified library brought array support to Python with dramatically improved performance.

Why NumPy is 50x Faster Than Python Lists

NumPy is written in C and compiled, while Python is interpreted. NumPy arrays are stored contiguously in memory and optimized for mathematical operations, making them dramatically faster for numerical computations than Python's native list data structure.

Arrays vs Lists: Key Differences

Data Type Homogeneity

Python lists can store mixed data types (integers, floats, strings) in one collection. NumPy arrays enforce a single data type across all elements—if you mix types, NumPy converts everything to a common type (usually string or float).

Performance & Memory Efficiency

NumPy arrays are much faster (up to 50x) and use significantly less memory than Python lists because they store homogeneous data contiguously and leverage C-level optimizations.

Vector Operations

With Python lists, you must manually loop through elements to perform operations. NumPy arrays support vectorized operations—apply the same operation to all elements at once using broadcasting, eliminating the need for explicit loops.

Array Creation & Basic Functions

Creating Arrays from Lists

Use np.array() to convert a Python list into a NumPy array. The resulting array will have a single data type; mixed types are automatically converted to a common type.

Generating Arrays with np.arange()

np.arange(start, stop, step) generates evenly spaced numbers similar to Python's range(). Note: the stop value is exclusive, so use stop+1 if you want to include it.

Generating Zeros and Ones

np.zeros(shape) creates an array filled with zeros; np.ones(shape) creates an array filled with ones. For 2D arrays, pass a tuple like (6, 5) for 6 rows and 5 columns.

Linear Spacing with np.linspace()

np.linspace(start, stop, num) generates exactly 'num' evenly spaced values between start and stop (inclusive). Unlike arange, the stop value is included, and spacing is uniform across all intervals.

Random Number Generation

np.random.rand(n) generates n random floats between 0 and 1 (normalized). np.random.randn(n) generates n random floats between -3 and 3 (standardized). np.random.randint(low, high, size) generates random integers in the range [low, high).

Array Attributes & Methods

Key Array Attributes

arr.shape returns dimensions (e.g., (3, 3) for 3 rows, 3 columns). arr.size returns total element count. arr.dtype returns the data type. These are properties, not methods—no parentheses needed.

Statistical Methods

arr.min() and arr.max() find minimum and maximum values. arr.sum() sums all elements. arr.mean() calculates average. arr.std() computes standard deviation. Use axis parameter (0 for columns, 1 for rows) to apply along specific dimensions.

Index-Finding Methods

arr.argmax() returns the index of the maximum element. arr.argmin() returns the index of the minimum element. These are useful for finding positions rather than values.

Reshaping & Resizing Arrays

Reshaping Arrays

arr.reshape(new_shape) reorganizes array elements into a new shape without changing the total element count. For example, a 30-element array can be reshaped to (6, 5) but not (5, 5). The product of dimensions must match.

Resizing Arrays

arr.resize(new_shape) modifies the array in-place to a new shape. Unlike reshape, resize can change the total number of elements (padding with zeros or truncating as needed).

Indexing & Slicing Vectors

Vector Indexing

Access individual elements using zero-based indexing: arr[0] gets the first element, arr[5] gets the sixth. Negative indices count from the end: arr[-1] is the last element.

Vector Slicing

arr[start:stop:step] extracts a portion of the array. The stop index is exclusive. Omit start to begin at 0, omit stop to go to the end, omit step for step=1. Example: arr[1:5] gets elements at indices 1, 2, 3, 4.

Indexing & Slicing Matrices

Selecting Single Elements

For a 2D array, arr[row, col] selects the element at that position. Row and column indices are zero-based. Example: arr[0, 4] gets the element in the first row, fifth column.

Selecting Rows and Columns

arr[row_index, :] selects an entire row. arr[:, col_index] selects an entire column. The colon means 'all elements in that dimension'.

Slicing Matrix Portions

arr[row_start:row_stop, col_start:col_stop] extracts a rectangular region. Example: arr[0:3, 1:3] gets rows 0–2 and columns 1–2. Both dimensions use the same slicing rules as vectors.

Boolean Indexing

Filtering with Boolean Conditions

Create a boolean array by applying a condition: bool_index = arr % 2 == 0 produces True/False for each element. Then use arr[bool_index] to extract only elements where the condition is True.

Boolean Array Requirements

The boolean array must have the same shape as the original array. Each True value keeps the corresponding element; each False value removes it. This is powerful for conditional filtering without explicit loops.

Arithmetic Operations & Broadcasting

Element-Wise Arithmetic

NumPy performs arithmetic operations element-by-element: arr1 + arr2 adds corresponding elements, arr1 * arr2 multiplies them, etc. Both arrays must have the same shape, or broadcasting rules apply.

Broadcasting Concept

Broadcasting allows operations between arrays of different shapes. If one array is smaller, NumPy automatically expands it to match the larger array's shape. Example: arr + 10 adds 10 to every element without explicit loops.

Deep Copy vs Shallow Copy

b = a creates a shallow copy—both variables point to the same data, so changes to b affect a. b = a.copy() creates a deep copy—b is independent, and changes don't affect a. Slicing creates a separate copy in memory.

Matrix Operations

Matrix Multiplication

Use arr1 @ arr2 (or np.dot(arr1, arr2)) for true matrix multiplication, not element-wise multiplication. In matrix multiplication, each element of the result is the dot product of a row from the first matrix and a column from the second.

Matrix Transpose

arr.T flips rows and columns: rows become columns and columns become rows. For a (3, 4) matrix, transpose produces a (4, 3) matrix. Useful for reshaping data for specific algorithms.

Advanced Array Manipulation

Vertical & Horizontal Stacking

np.vstack((arr1, arr2)) stacks arrays vertically (row-wise). np.hstack((arr1, arr2)) stacks horizontally (column-wise). Both require compatible shapes. Use tuples as arguments.

Column Stacking

np.column_stack((arr1, arr2)) treats 1D arrays as columns and combines them side-by-side into a 2D array. Useful for building data matrices from separate feature vectors.

Splitting Arrays

np.hsplit(arr, n) splits horizontally into n equal parts. np.vsplit(arr, n) splits vertically into n equal parts. The array dimensions must be evenly divisible by n.

Practical Exercises: Sudoku Validation

Sudoku Rules

A valid Sudoku has 9 rows, 9 columns, and nine 3×3 blocks. Each row, column, and block must contain the digits 1–9 exactly once. The sum of each row, column, and block must equal 45 (sum of 1–9).

Validating Rows and Columns

Use np.sum(sudoku, axis=1) to sum each row and check if all equal 45. Use np.sum(sudoku, axis=0) to sum each column. If any sum ≠ 45, the Sudoku is invalid.

Validating 3×3 Blocks

Extract each 3×3 block using slicing: sudoku[i:i+3, j:j+3] where i and j iterate 0, 3, 6. Sum each block and verify it equals 45. Use nested loops with step=3 to iterate through all nine blocks.

Practical Exercises: Student Data Analysis

Array Shape & Dimensions

Use arr.shape to get dimensions. For a student dataset with 5 students and 3 subjects (age, math, science), shape is (5, 3)—5 rows, 3 columns.

Calculating Averages

np.mean(arr[:, col_index]) calculates the average of a specific column. np.mean(arr, axis=0) calculates column-wise averages; axis=1 calculates row-wise averages.

Extracting Specific Columns

Use arr[:, col_index] to extract an entire column. Example: arr[:, 1] gets all math marks. Use boolean indexing to filter: arr[arr[:, 1] > 90] gets rows where math marks exceed 90.

Finding Maximum Values

np.max(arr[:, col_index]) finds the highest value in a column. Example: np.max(arr[:, 2]) finds the highest science mark.

Conditional Filtering with Multiple Conditions

Combine conditions using & (and) operator: (arr[:, 1] > 90) & (arr[:, 2] > 80) filters rows where both math > 90 AND science > 80. Wrap each condition in parentheses.

Modifying Array Values

Use arr[:, col_index] += value to add to all elements in a column. Use arr[condition] = value to replace elements matching a condition. Example: arr[arr[:, 2] < 75, 2] = 0 sets science marks below 75 to zero.

Notable quotes

NumPy is up to 50 times faster than Python lists because it's written in C. — Instructor
Broadcasting allows you to perform operations on arrays of different shapes without explicit loops. — Instructor
Whatever you do inside a sliced portion, changes won't affect the main array because slices create a different location in RAM. — Instructor

Action items

  • Download and install Anaconda Distribution or set up Jupyter Notebook in VS Code to follow along with code examples.
  • Enable auto-completion and auto-close brackets in your Jupyter notebook settings for better coding experience.
  • Practice creating arrays using np.array(), np.arange(), np.linspace(), np.zeros(), np.ones(), and random functions.
  • Master array indexing and slicing for both 1D vectors and 2D matrices using the [start:stop:step] syntax.
  • Implement the Sudoku validation exercise by checking row sums, column sums, and 3×3 block sums equal 45.
  • Complete the student data analysis exercises: calculate averages, filter by conditions, modify values, and extract specific columns.
  • Experiment with broadcasting by performing arithmetic operations between arrays of different shapes.
  • Practice deep copy vs shallow copy to understand memory management in NumPy.
Sheryians AI School
2 hr video
3 min read
NumPy Mastery: Arrays, Operations & Real Data Projects
You just saved 1 hr 57 min.
The big takeaway
Complete guide to NumPy covering array creation, indexing, slicing, arithmetic operations, broadcasting, matrix operations, and practical exercises including Sudoku validation and student data analysis.
Getting Started: Notebooks & Setup
What is a Jupyter Notebook
A Jupyter Notebook is a special file (.ipynb) that lets you write code, run it, and see output in one place. Unlike Python files, notebooks support markdown text, equations, images, and charts—making them ideal for data visualization and analysis workflows.
Three Ways to Use Notebooks
You can use Jupyter Notebooks via: (1) Anaconda Distribution with Jupyter Notebook installed locally, (2) VS Code with Jupyter extension, or (3) Google Colab (cloud-based with free GPU support). Each has trade-offs between ease of setup and available resources.
1
Jupyter Notebook (Anaconda)
Local, full control, all libraries pre-installed
2
VS Code + Jupyter
Lightweight, requires manual package installation
3
Google Colab
Cloud-based, free GPU, everything pre-installed
Notebook environments ranked by setup complexity and features
Key Notebook Settings
Enable auto-completion in settings to get function suggestions while typing. Enable auto-close brackets to avoid syntax errors. These settings are essential because NumPy has thousands of functions you won't remember.
NumPy Origin & Why It Matters
NumPy's Evolution
NumPy was created in 2005 by Travis Oliphant by combining two earlier libraries: Numeric (created 1995) and Numarray. This unified library brought array support to Python with dramatically improved performance.
1995
Numeric Library created for array support
Early 2000s
Numarray developed by Space Telescope Science Institute
2005
Travis Oliphant combines both into NumPy
NumPy development timeline
Why NumPy is 50x Faster Than Python Lists
NumPy is written in C and compiled, while Python is interpreted. NumPy arrays are stored contiguously in memory and optimized for mathematical operations, making them dramatically faster for numerical computations than Python's native list data structure.
50x
NumPy arrays faster than Python lists
Performance advantage due to C implementation and compilation
Arrays vs Lists: Key Differences
Data Type Homogeneity
Python lists can store mixed data types (integers, floats, strings) in one collection. NumPy arrays enforce a single data type across all elements—if you mix types, NumPy converts everything to a common type (usually string or float).
Python List
[1, 3.5, 'hello'] - mixed types allowed
NumPy Array
['1' '3.5' 'hello'] - all converted to strings
Data type handling: lists vs arrays
Performance & Memory Efficiency
NumPy arrays are much faster (up to 50x) and use significantly less memory than Python lists because they store homogeneous data contiguously and leverage C-level optimizations.
Python Lists
1 relative speed
NumPy Arrays
50 relative speed
Performance comparison: speed and memory efficiency
Vector Operations
With Python lists, you must manually loop through elements to perform operations. NumPy arrays support vectorized operations—apply the same operation to all elements at once using broadcasting, eliminating the need for explicit loops.
Array Creation & Basic Functions
Creating Arrays from Lists
Use np.array() to convert a Python list into a NumPy array. The resulting array will have a single data type; mixed types are automatically converted to a common type.
Generating Arrays with np.arange()
np.arange(start, stop, step) generates evenly spaced numbers similar to Python's range(). Note: the stop value is exclusive, so use stop+1 if you want to include it.
np.arange(1, 11)
Generates 1 through 10
Stop value is exclusive; use 11 to include 10
Generating Zeros and Ones
np.zeros(shape) creates an array filled with zeros; np.ones(shape) creates an array filled with ones. For 2D arrays, pass a tuple like (6, 5) for 6 rows and 5 columns.
Linear Spacing with np.linspace()
np.linspace(start, stop, num) generates exactly 'num' evenly spaced values between start and stop (inclusive). Unlike arange, the stop value is included, and spacing is uniform across all intervals.
np.linspace(1, 5, 5)
Generates [1, 2, 3, 4, 5] with equal spacing
Useful for creating evenly distributed sample points
Random Number Generation
np.random.rand(n) generates n random floats between 0 and 1 (normalized). np.random.randn(n) generates n random floats between -3 and 3 (standardized). np.random.randint(low, high, size) generates random integers in the range [low, high).
Array Attributes & Methods
Key Array Attributes
arr.shape returns dimensions (e.g., (3, 3) for 3 rows, 3 columns). arr.size returns total element count. arr.dtype returns the data type. These are properties, not methods—no parentheses needed.
Statistical Methods
arr.min() and arr.max() find minimum and maximum values. arr.sum() sums all elements. arr.mean() calculates average. arr.std() computes standard deviation. Use axis parameter (0 for columns, 1 for rows) to apply along specific dimensions.
Index-Finding Methods
arr.argmax() returns the index of the maximum element. arr.argmin() returns the index of the minimum element. These are useful for finding positions rather than values.
Reshaping & Resizing Arrays
Reshaping Arrays
arr.reshape(new_shape) reorganizes array elements into a new shape without changing the total element count. For example, a 30-element array can be reshaped to (6, 5) but not (5, 5). The product of dimensions must match.
Original
1D array with 30 elements
Reshaped
2D array (6 rows × 5 columns)
Reshape requires matching total element count
Resizing Arrays
arr.resize(new_shape) modifies the array in-place to a new shape. Unlike reshape, resize can change the total number of elements (padding with zeros or truncating as needed).
Indexing & Slicing Vectors
Vector Indexing
Access individual elements using zero-based indexing: arr[0] gets the first element, arr[5] gets the sixth. Negative indices count from the end: arr[-1] is the last element.
Vector Slicing
arr[start:stop:step] extracts a portion of the array. The stop index is exclusive. Omit start to begin at 0, omit stop to go to the end, omit step for step=1. Example: arr[1:5] gets elements at indices 1, 2, 3, 4.
arr[1:5:2]
Gets indices 1 and 3 (step of 2)
Slicing syntax: [start:stop:step]
Indexing & Slicing Matrices
Selecting Single Elements
For a 2D array, arr[row, col] selects the element at that position. Row and column indices are zero-based. Example: arr[0, 4] gets the element in the first row, fifth column.
Selecting Rows and Columns
arr[row_index, :] selects an entire row. arr[:, col_index] selects an entire column. The colon means 'all elements in that dimension'.
Slicing Matrix Portions
arr[row_start:row_stop, col_start:col_stop] extracts a rectangular region. Example: arr[0:3, 1:3] gets rows 0–2 and columns 1–2. Both dimensions use the same slicing rules as vectors.
Boolean Indexing
Filtering with Boolean Conditions
Create a boolean array by applying a condition: bool_index = arr % 2 == 0 produces True/False for each element. Then use arr[bool_index] to extract only elements where the condition is True.
Boolean Array Requirements
The boolean array must have the same shape as the original array. Each True value keeps the corresponding element; each False value removes it. This is powerful for conditional filtering without explicit loops.
Arithmetic Operations & Broadcasting
Element-Wise Arithmetic
NumPy performs arithmetic operations element-by-element: arr1 + arr2 adds corresponding elements, arr1 * arr2 multiplies them, etc. Both arrays must have the same shape, or broadcasting rules apply.
Broadcasting Concept
Broadcasting allows operations between arrays of different shapes. If one array is smaller, NumPy automatically expands it to match the larger array's shape. Example: arr + 10 adds 10 to every element without explicit loops.
arr + 10
Broadcasts scalar to all elements
Broadcasting eliminates the need for manual loops
Deep Copy vs Shallow Copy
b = a creates a shallow copy—both variables point to the same data, so changes to b affect a. b = a.copy() creates a deep copy—b is independent, and changes don't affect a. Slicing creates a separate copy in memory.
Shallow Copy (b = a)
Changes to b affect a
Deep Copy (b = a.copy())
Changes to b don't affect a
Memory sharing vs independence
Matrix Operations
Matrix Multiplication
Use arr1 @ arr2 (or np.dot(arr1, arr2)) for true matrix multiplication, not element-wise multiplication. In matrix multiplication, each element of the result is the dot product of a row from the first matrix and a column from the second.
Matrix Transpose
arr.T flips rows and columns: rows become columns and columns become rows. For a (3, 4) matrix, transpose produces a (4, 3) matrix. Useful for reshaping data for specific algorithms.
Advanced Array Manipulation
Vertical & Horizontal Stacking
np.vstack((arr1, arr2)) stacks arrays vertically (row-wise). np.hstack((arr1, arr2)) stacks horizontally (column-wise). Both require compatible shapes. Use tuples as arguments.
Column Stacking
np.column_stack((arr1, arr2)) treats 1D arrays as columns and combines them side-by-side into a 2D array. Useful for building data matrices from separate feature vectors.
Splitting Arrays
np.hsplit(arr, n) splits horizontally into n equal parts. np.vsplit(arr, n) splits vertically into n equal parts. The array dimensions must be evenly divisible by n.
Practical Exercises: Sudoku Validation
Sudoku Rules
A valid Sudoku has 9 rows, 9 columns, and nine 3×3 blocks. Each row, column, and block must contain the digits 1–9 exactly once. The sum of each row, column, and block must equal 45 (sum of 1–9).
45
Sum of each valid row, column, or 3×3 block
Sudoku validation uses sum checks
Validating Rows and Columns
Use np.sum(sudoku, axis=1) to sum each row and check if all equal 45. Use np.sum(sudoku, axis=0) to sum each column. If any sum ≠ 45, the Sudoku is invalid.
Validating 3×3 Blocks
Extract each 3×3 block using slicing: sudoku[i:i+3, j:j+3] where i and j iterate 0, 3, 6. Sum each block and verify it equals 45. Use nested loops with step=3 to iterate through all nine blocks.
Practical Exercises: Student Data Analysis
Array Shape & Dimensions
Use arr.shape to get dimensions. For a student dataset with 5 students and 3 subjects (age, math, science), shape is (5, 3)—5 rows, 3 columns.
Calculating Averages
np.mean(arr[:, col_index]) calculates the average of a specific column. np.mean(arr, axis=0) calculates column-wise averages; axis=1 calculates row-wise averages.
Extracting Specific Columns
Use arr[:, col_index] to extract an entire column. Example: arr[:, 1] gets all math marks. Use boolean indexing to filter: arr[arr[:, 1] > 90] gets rows where math marks exceed 90.
Finding Maximum Values
np.max(arr[:, col_index]) finds the highest value in a column. Example: np.max(arr[:, 2]) finds the highest science mark.
Conditional Filtering with Multiple Conditions
Combine conditions using & (and) operator: (arr[:, 1] > 90) & (arr[:, 2] > 80) filters rows where both math > 90 AND science > 80. Wrap each condition in parentheses.
Modifying Array Values
Use arr[:, col_index] += value to add to all elements in a column. Use arr[condition] = value to replace elements matching a condition. Example: arr[arr[:, 2] < 75, 2] = 0 sets science marks below 75 to zero.
Worth quoting
"NumPy is up to 50 times faster than Python lists because it's written in C."
— Instructor, at [18:57]
"Broadcasting allows you to perform operations on arrays of different shapes without explicit loops."
— Instructor, at [70:39]
"Whatever you do inside a sliced portion, changes won't affect the main array because slices create a different location in RAM."
— Instructor, at [75:14]
Try this
Download and install Anaconda Distribution or set up Jupyter Notebook in VS Code to follow along with code examples.
Enable auto-completion and auto-close brackets in your Jupyter notebook settings for better coding experience.
Practice creating arrays using np.array(), np.arange(), np.linspace(), np.zeros(), np.ones(), and random functions.
Master array indexing and slicing for both 1D vectors and 2D matrices using the [start:stop:step] syntax.
Implement the Sudoku validation exercise by checking row sums, column sums, and 3×3 block sums equal 45.
Complete the student data analysis exercises: calculate averages, filter by conditions, modify values, and extract specific columns.
Experiment with broadcasting by performing arithmetic operations between arrays of different shapes.
Practice deep copy vs shallow copy to understand memory management in NumPy.
Made with Glimpse by Wozart
glimpse.wozart.com/v/l53hokiq
Share this infographic

More like this