Numpy Notes (Video 6-10)
➔ Numpy arrays VS Python Lists:
Numpy arrays faster and memory efficient:
Python lists are like a box of items with labels and bubble wrap
NumPy arrays are like tightly-packed bricks ready for machines to process
Numpy Notes (Video 6-10)
NumPy Part 6 – Indexing, Slicing, and Iteration
🔑 Concepts Covered:
● Accessing individual elements (1D, 2D) (Indexing)
● Extracting parts of arrays (slicing)
● Using negative indices
● Iterating through arrays
📌 Syntax & Patterns:
🔹 Indexing:
arr[i] # ith element in 1D array
arr[i, j] # element at ith row and jth column (2D)
🔹 Slicing:
arr[start:stop:step] # Like Python lists
arr[:, j] # All rows, jth column
arr[i, :] # ith row, all columns
arr[::2, 1:] # Every 2nd row, from column 1 onwards
🔹 Negative Indexing:
arr[-1] # Last element (1D)
arr[:, -1] # Last column (2D)
🧪 Example:
arr = [Link]([[1,2,3],
[4,5,6],
[7,8,9]])
print(arr[1, 2]) # Output: 6
print(arr[:, 1]) # Output: [2 5 8]
print(arr[:2, :2]) # Output: [[1 2], [4 5]]
✅ Best Practices:
Numpy Notes (Video 6-10)
● Prefer arr[i, j] over arr[i][j] for performance and clarity.
● Slices are views (not copies). Use .copy() if needed:
subarr = arr[:, :2].copy()
Difference Between:
🔴 arr7 = arr6[1:2, 0:2]
🟢 arr7 = arr6[1:2, 0:2].copy()
⚙️ Both lines extract a submatrix from arr6:
They give you a 2D slice of shape (1, 2) — for example:
● [[13, 14]]
But the difference is in memory behavior — specifically:
Case 1: arr7 = arr6[1:2, 0:2] → View
● This creates a view of the original array
● It shares the same memory as arr6
● Faster, but
● Changes to arr7 also change arr6
🔧 Example:
● arr7 = arr6[1:2, 0:2]
● arr7[0, 0] = 999
● print(arr6[1, 0]) # → Will show 999
Numpy Notes (Video 6-10)
Case 2: arr7 = arr6[1:2, 0:2].copy() → Copy
● This creates a new array with its own memory
● Changes to arr7 will not affect arr6
● Safe for modification or isolation
🔧 Example:
● arr7 = arr6[1:2, 0:2].copy()
● arr7[0, 0] = 999
● print(arr6[1, 0]) # → Will still show original value (e.g., 13)
Summary Table
Expression Memory Modifies Use Case
Type Original?
arr6[1:2, View Yes Fast, when you want to reflect
0:2] changes in original
arr6[1:2, Copy No Safe, when you want independent
0:2].copy data
()
🔥 Rule of Thumb:
Use .copy() whenever you plan to modify a subarray and don’t want the
changes reflected in the original array.
NumPy Part 7 – NumPy Operations
🔑 Concepts Covered:
Numpy Notes (Video 6-10)
● Element-wise arithmetic
● Broadcasting
● Logical operations & filtering
● Aggregation
📌 Syntax & Patterns:
🔹 Arithmetic: (happens elementwise)
arr + 10
arr * 10
arr1 + arr2
arr1 * arr2
🔹 Logical & Comparison:
arr > 5
np.logical_and(arr > 2, arr < 6)
np.logical_not(arr < 4)
🔹 Aggregation:
[Link]()
[Link](), [Link]()
[Link](axis=0) # Column-wise
[Link](axis=1) # Row-wise
🧪 Example:
arr = [Link]([[1, 2], [3, 4]])
print(arr + 10) # [[11, 12], [13, 14]]
print(arr > 2) # [[False, False], [True, True]]
print([Link](axis=0)) # [4 6]
✅ Best Practices:
● Use vectorized operations instead of Python loops.
i.e Avoid for loops when doing math on NumPy arrays. Use arr + something, arr
* something, [Link](arr) etc.
Numpy Notes (Video 6-10)
● Know broadcasting rules: small arrays are stretched to match larger shapes.
i.e NumPy can automatically stretch (broadcast) a smaller array to match the shape of a
larger array without copying data.
Example:
a = [Link]([[1, 2, 3],
[4, 5, 6]]) # Shape: (2, 3)
b = [Link]([10, 20, 30]) # Shape: (3,)
You can do:
print(a + b)
Output:
[[11 22 33]
[14 25 36]]
NumPy automatically broadcasts b to this shape:
[[10 20 30]
[10 20 30]]
But this would cause an error:
c = [Link]([10, 20]) # Shape: (2,)
a + c # incompatible shapes (2,3) + (2,)
Numpy Notes (Video 6-10)
Think of it like this:
Broadcasting = NumPy’s smart way of temporarily matching shapes without wasting
memory.
NumPy Part 8 – Reshaping NumPy Arrays
🔑 Concepts Covered:
● Changing shape of arrays
● Flattening arrays
● Transpose of arrays
📌 Syntax & Patterns:
🔹 Reshape:
[Link](new_rows, new_cols)
🔹 Flatten:
[Link]() # Returns view (fast, memory efficient)
[Link]() # Returns copy (safe for independent edits)
ex.
arr10 = [Link]([[1, 2, 3],
[4, 5, 6]])
flat1=[Link]()
flat2=[Link]()
output for both:
array([1, 2, 3, 4, 5, 6])
But changes in flat1 will reflect in arr10 as well
🔹 Transpose:
Numpy Notes (Video 6-10)
arr.T
🧪 Example:
arr = [Link](1, 13)
reshaped = [Link](3, 4)
print(reshaped.T)
✅ Best Practices:
● Ensure reshaped arrays maintain the same total number of elements.
● Use .ravel() when no modifications will be made, .flatten() when
modifications are needed.
Note: Fancy Indexing
🔑 Concepts Covered:
● Indexing using arrays or lists of indices
📌 Syntax & Patterns:
arr[[0, 2]] # Selects 1st and 3rd rows
arr[[0, 2], [1, 0]] # Selects elements at (0,1) and (2,0)
🧪 Example:
arr = [Link]([[10, 20], [30, 40], [50, 60]])
print(arr[[0, 2], [1, 0]]) # Output: [20 50]
✅ Best Practices:
● Fancy indexing always returns a copy.
● Useful for non-contiguous data selection or row reordering.
Numpy Notes (Video 6-10)
NumPy Part 10 – Boolean Indexing
🔑 Concepts Covered:
● Using conditions to filter arrays
● Masking arrays with boolean arrays
📌 Syntax & Patterns:
🔹 Create Mask:
mask = arr > 25
🔹 Apply Mask:
arr[mask] # Filters elements where condition is True
🔹 Combine Conditions:
arr[(arr > 20) & (arr < 40)]
🧪 Example:
arr = [Link]([10, 25, 30, 45])
print(arr[arr > 25]) # Output: [30 45]
✅ Best Practices:
● Powerful tool for filtering and subsetting arrays.
● Combine multiple conditions using &, |, and ~ (not).
✅ Recap Tips for Videos 6–10:
Feature Key Notes
Indexing Use arr[i, j] syntax for clarity
Numpy Notes (Video 6-10)
Slicing Returns a view; use .copy() if copy is needed
Arithmetic Ops Vectorized, fast, and memory efficient
Reshape & Flatten Ensure element counts match in reshape
Fancy Indexing Returns copy; good for custom ordering
Boolean Indexing Filter arrays using logical conditions