Session 9

πŸ”’ NumPy & List Comprehensions

Powerful numerical computing and elegant list creation

πŸ“š 10 Topics ⏱️ 50 min read 🎯 Intermediate Level

πŸ—ΊοΈ What You'll Learn

πŸ“Š NumPy Arrays
βž• Array Operations
πŸ“ Array Reshaping
πŸ”’ Mathematical Functions
πŸ“ List Comprehensions
πŸ“– Dict Comprehensions

πŸ“˜ Same topic in the course notebook

Session_9 has NumPy, List Comprehension, and Lambda notebooksβ€”same topics. Run them to practice arrays and comprehensions.

πŸ“ List Comprehensions

9.1

⚑ Elegant List Creation

List comprehensions are a concise way to create lists in a single line!

πŸ”„ Traditional vs Comprehension

    TRADITIONAL (4 lines)              LIST COMPREHENSION (1 line)
    ─────────────────────              ─────────────────────────────
    squares = []                       squares = [x**2 for x in range(5)]
    for x in range(5):
        squares.append(x**2)
    
    Same result: [0, 1, 4, 9, 16]
    
    Syntax: [expression for item in iterable]
          
Python From Source
# List comprehensions from Session 9

# Basic list comprehension
squares = [x**2 for x in range(1, 6)]
print("Squares:", squares)

# With condition (filter)
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print("Even squares:", even_squares)

# Transform strings
names = ["alice", "bob", "charlie"]
upper_names = [name.upper() for name in names]
print("Uppercase:", upper_names)

# With if-else
numbers = [1, 2, 3, 4, 5]
labels = ["even" if x % 2 == 0 else "odd" for x in numbers]
print("Labels:", labels)

# Nested list comprehension (flattening)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print("Flattened:", flat)
Output
Squares: [1, 4, 9, 16, 25]
Even squares: [4, 16, 36, 64, 100]
Uppercase: ['ALICE', 'BOB', 'CHARLIE']
Labels: ['odd', 'even', 'odd', 'even', 'odd']
Flattened: [1, 2, 3, 4, 5, 6, 7, 8, 9]
9.2

πŸ“– Dictionary & Set Comprehensions

Python From Source
# Dictionary comprehension
squares_dict = {x: x**2 for x in range(1, 6)}
print("Squares dict:", squares_dict)

# From two lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
people = {name: age for name, age in zip(names, ages)}
print("People:", people)

# Set comprehension (removes duplicates)
numbers = [1, 2, 2, 3, 3, 3]
unique_squares = {x**2 for x in numbers}
print("Unique squares:", unique_squares)
Output
Squares dict: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
People: {'Alice': 25, 'Bob': 30, 'Charlie': 35}
Unique squares: {1, 4, 9}

πŸ”’ NumPy - Numerical Python

9.3

πŸ“Š What is NumPy?

NumPy is the foundation for numerical computing in Python. It provides powerful array objects and mathematical functions!

⚑ Why NumPy?

    Python List              NumPy Array
    ─────────────            ───────────
    [1, 2, 3, 4, 5]         np.array([1, 2, 3, 4, 5])
    
    ❌ Slow loops            βœ… Fast vectorized operations
    ❌ Element-by-element    βœ… Whole-array operations
    ❌ Memory inefficient    βœ… Memory efficient
    
    NumPy can be 10-100x faster! πŸš€
          
Python From Source
# NumPy basics from Session 9
import numpy as np

# Create arrays
arr1 = np.array([1, 2, 3, 4, 5])
print("Array:", arr1)
print("Type:", type(arr1))
print("Shape:", arr1.shape)
print("Data type:", arr1.dtype)

# 2D array
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("\\n2D Array:")
print(arr2d)
print("Shape:", arr2d.shape)
Output
Array: [1 2 3 4 5]
Type: <class 'numpy.ndarray'>
Shape: (5,)
Data type: int64

2D Array:
[[1 2 3]
 [4 5 6]]
Shape: (2, 3)
9.4

πŸ—οΈ Creating Arrays

Python From Source
# Array creation functions from Session 9
import numpy as np

# zeros - array of all zeros
zeros = np.zeros(5)
print("Zeros:", zeros)

# ones - array of all ones
ones = np.ones((2, 3))  # 2x3 matrix
print("Ones:\\n", ones)

# arange - like range but returns array
range_arr = np.arange(0, 10, 2)
print("Arange:", range_arr)

# linspace - evenly spaced numbers
linspace_arr = np.linspace(0, 1, 5)  # 5 numbers from 0 to 1
print("Linspace:", linspace_arr)

# random arrays
random_arr = np.random.rand(3)  # 3 random numbers [0, 1)
print("Random:", random_arr)

random_int = np.random.randint(1, 10, size=5)  # 5 random integers 1-9
print("Random integers:", random_int)

# Identity matrix
identity = np.eye(3)
print("Identity matrix:\\n", identity)
Output
Zeros: [0. 0. 0. 0. 0.]
Ones:
 [[1. 1. 1.]
 [1. 1. 1.]]
Arange: [0 2 4 6 8]
Linspace: [0.   0.25 0.5  0.75 1.  ]
Random: [0.123... 0.456... 0.789...]
Random integers: [3 7 2 9 1]
Identity matrix:
 [[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
9.5

βž• Array Operations

Python From Source
# Array operations from Session 9
import numpy as np

arr = np.array([1, 2, 3, 4, 5])

# Element-wise operations
print("Original:", arr)
print("arr + 10:", arr + 10)
print("arr * 2:", arr * 2)
print("arr ** 2:", arr ** 2)
print("arr / 2:", arr / 2)

# Operations between arrays
arr2 = np.array([10, 20, 30, 40, 50])
print("\\narr + arr2:", arr + arr2)
print("arr * arr2:", arr * arr2)

# Comparison operations
print("\\narr > 2:", arr > 2)
print("arr == 3:", arr == 3)
Output
Original: [1 2 3 4 5]
arr + 10: [11 12 13 14 15]
arr * 2: [ 2  4  6  8 10]
arr ** 2: [ 1  4  9 16 25]
arr / 2: [0.5 1.  1.5 2.  2.5]

arr + arr2: [11 22 33 44 55]
arr * arr2: [ 10  40  90 160 250]

arr > 2: [False False  True  True  True]
arr == 3: [False False  True False False]
9.6

πŸ” Indexing & Slicing

Python From Source
# NumPy indexing from Session 9
import numpy as np

arr = np.array([10, 20, 30, 40, 50])

# Basic indexing
print("First element:", arr[0])
print("Last element:", arr[-1])
print("Slice [1:4]:", arr[1:4])

# 2D array indexing
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("\\nMatrix:")
print(matrix)
print("Row 0:", matrix[0])
print("Element [1,2]:", matrix[1, 2])
print("Column 1:", matrix[:, 1])

# Boolean indexing (filtering)
print("\\nElements > 30:", arr[arr > 30])
print("Even elements:", arr[arr % 20 == 0])
Output
First element: 10
Last element: 50
Slice [1:4]: [20 30 40]

Matrix:
[[1 2 3]
 [4 5 6]
 [7 8 9]]
Row 0: [1 2 3]
Element [1,2]: 6
Column 1: [2 5 8]

Elements > 30: [40 50]
Even elements: [20 40]
9.7

πŸ“ Mathematical Functions

Python From Source
# NumPy math functions from Session 9
import numpy as np

arr = np.array([1, 2, 3, 4, 5])

# Aggregation functions
print("Sum:", np.sum(arr))
print("Mean:", np.mean(arr))
print("Max:", np.max(arr))
print("Min:", np.min(arr))
print("Std Dev:", np.std(arr))

# Mathematical functions
print("\\nSquare root:", np.sqrt(arr))
print("Exponential:", np.exp(arr))
print("Log:", np.log(arr))

# Matrix operations
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

print("\\nMatrix A:")
print(A)
print("Matrix B:")
print(B)
print("A @ B (matrix multiplication):")
print(np.dot(A, B))
Output
Sum: 15
Mean: 3.0
Max: 5
Min: 1
Std Dev: 1.4142135...

Square root: [1.   1.41 1.73 2.   2.24]
Exponential: [  2.72   7.39  20.09  54.60 148.41]
Log: [0.   0.69 1.10 1.39 1.61]

Matrix A:
[[1 2]
 [3 4]]
Matrix B:
[[5 6]
 [7 8]]
A @ B (matrix multiplication):
[[19 22]
 [43 50]]
9.8

πŸ”„ Reshaping Arrays

Python From Source
# Reshaping arrays from Session 9
import numpy as np

arr = np.arange(1, 13)  # [1, 2, 3, ..., 12]
print("Original:", arr)
print("Shape:", arr.shape)

# Reshape to 3x4
reshaped = arr.reshape(3, 4)
print("\\nReshaped to 3x4:")
print(reshaped)

# Reshape to 4x3
reshaped2 = arr.reshape(4, 3)
print("\\nReshaped to 4x3:")
print(reshaped2)

# Flatten back to 1D
flat = reshaped.flatten()
print("\\nFlattened:", flat)

# Transpose
print("\\nTransposed:")
print(reshaped.T)
Output
Original: [ 1  2  3  4  5  6  7  8  9 10 11 12]
Shape: (12,)

Reshaped to 3x4:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

Reshaped to 4x3:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

Flattened: [ 1  2  3  4  5  6  7  8  9 10 11 12]

Transposed:
[[ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]
 [ 4  8 12]]

πŸ“‹ Quick Reference

πŸ“ List Comprehension Syntax

PatternExample
Basic[x**2 for x in range(5)]
With filter[x for x in range(10) if x%2==0]
With if-else["even" if x%2==0 else "odd" for x in nums]
Dict{k: v for k, v in zip(keys, vals)}
Set{x**2 for x in nums}

πŸ”’ NumPy Functions

FunctionDescription
np.array()Create array
np.zeros(n)Array of zeros
np.ones(n)Array of ones
np.arange()Range as array
np.linspace()Evenly spaced
arr.reshape()Change shape
np.sum/mean/maxAggregations

🚫 Common Mistakes (NumPy)

πŸ’­ Short reflection

In one sentence: why is NumPy faster than using Python lists for numerical operations on large arrays?

βœ… CORE (Must know)

πŸ“š NON-CORE (Good to know)

Complete code from course notebook: numpy1.ipynb

Every line of code from the course notebook (verbatim).

# --- Code cell 2 ---
modules/packages/libraries---3rd party lib--they have no connection base python

# --- Code cell 4 ---
! pip install numpy

# --- Code cell 5 ---
import numpy as np # importing numpy package using alias np for easy reference
#import numpy as num # this is fine as well but not widely used

# --- Code cell 7 ---
list1=[1,2,3,4]

# --- Code cell 8 ---
array = np.array(list1) # create numpy array
print(type(array))
print(array)

# --- Code cell 9 ---
array.ndim

# --- Code cell 11 ---

gross = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])

print(gross)

# --- Code cell 12 ---
print(gross.shape)

# --- Code cell 13 ---
gross.ndim

# --- Code cell 14 ---
gross.size

# --- Code cell 15 ---
# np array is useful for matrix operations
array = np.array([[1, 2, 3, 4], [5, 6, 7, 8],[50, 60, 70, 80]])

print(array.shape)

# --- Code cell 16 ---
print(array)

# --- Code cell 17 ---
# syntax for indexing-2D
array[row_ind,col_ind]

# --- Code cell 18 ---
print(array[2][2])

# --- Code cell 19 ---
print(array[1,1])

# --- Code cell 21 ---
array.shape

# --- Code cell 22 ---
array

# --- Code cell 23 ---
new_array = array.reshape(4, 3)
print(new_array)

# --- Code cell 24 ---
#Flattening array: Converting multidimensional array to 1 D
new_array = array.reshape(-1)
print(new_array)

# --- Code cell 25 ---
#Flattening array: Converting multidimensional array to 1 D
new_array = array.flatten()
print(new_array)

# --- Code cell 26 ---
#Sort array
array = np.array([23,43,5,8,90,100]) # ascending order
print(np.sort(array))

# --- Code cell 27 ---
print(np.sort(array)[::-1])    # descending

# --- Code cell 28 ---
otp---random otps

# --- Code cell 30 ---
#4 digit otp---using random

# --- Code cell 31 ---
# Generate random number
from numpy import random
number = random.randint(100000,999999)
print(number)

# --- Code cell 32 ---
# Generate random number
from numpy import random
number = random.randint(low=1000,high=9999,size=(12,12))
print(number)

# --- Code cell 33 ---
# Generate random number
from numpy import random
np.random.seed(9)
number = random.uniform(1000,9999,size=[2,2]) # random float values
print(number)

# --- Code cell 34 ---
list1=[1,2,3,4]
array=np.array(list1)
print(type(array))
print(array)
print(array.shape)
print(array.ndim)
print(np.random.randint(100,999))

# --- Code cell 36 ---
# Dot product using numpy array

import numpy as np

# Vectors as 1D numpy arrays
a = np.array([[1, 2, 3],[4,2,6]])
b = np.array([[4, 5, 6],[5,1,9]])

# 4*1 + 5*2 + 3*6
print("dot product output:", np.dot(a, b.T))

# --- Code cell 38 ---
#Tranpose
array = np.array([[1, 2, 3, 4], [5, 6, 7, 8],[50, 60, 70, 80]])
print(array)
print(array.shape)

# --- Code cell 39 ---
new_array = array.transpose()
print(new_array)
print(new_array.shape)

# --- Code cell 40 ---
new_array = array.T
print(new_array)
print(new_array.shape)

Complete code from course notebook: List_Comprehension (1).ipynb

Every line of code from the course notebook (verbatim).

# --- Code cell 1 ---
# list comprehensions
# lambda func
# numpy

# --- Code cell 2 ---
what is list comprehension?
# it is a concise way to create lists in python.
# it provides a shorter,more readable and efficient way to generate lists compared to using loops

# --- Code cell 3 ---
# traditional list creation using loops
numbers=[]
for i in range(1,6):
  numbers.append(i)
print(numbers)

# --- Code cell 4 ---
# syntax for list comprehension
# [expression for item in iterable if condition(optional)]

# expression---operation performed on each element---x*2
# item---each element in the iterable--x
# iterable---The data structure being iterated---range(1,6)
# condition---opitional filter to include only specific elements

# --- Code cell 5 ---
# list comprehension(same output in one line)
numbers=[i**2 for i in range(1,6) if i%2==0]
print(numbers)

# --- Code cell 6 ---
# create a list from range

numbers=[i for i in range(1,11)]
print(numbers)

# --- Code cell 7 ---
# create a list of squares
squares=[x**2 for x in range(1,13)]
print(squares)

# --- Code cell 8 ---
# filter even numbers
even_num=[(x*2,x**4)for x in range(1,11) if x%2==0]
print(even_num)

# --- Code cell 9 ---
# filtering words based on length
words=["apple","banana","cherry","date","machine","learning"]
short_words=[word for word in words if len(word)<=5]
print(short_words)

# --- Code cell 10 ---
#using if else in list comprehension
# replace even numbers with "even"and odd numbers with ""odd""
labels=[ "even" if x%2==0 else "odd" for x in range(1,11)  ]
print(labels)

# --- Code cell 11 ---
scores=[82,80,26,75,60,55,44,67]
result=["pass" if score>=50 else "fail" for score in scores]
print(result)

# --- Code cell 12 ---
# converting dictionary into list
students={"alice":34,"grace":45}
names=[name for name in students]
print(names)

# --- Code cell 13 ---
users=["alice@outlook.com","bob@gmail.com","charlie@yahoo.com","david@outlook.com"]
outlook_users=[user for user in users if "@outlook.com" in user]
print(outlook_users)

Complete code from course notebook: Python_Lambda_Functions.ipynb

Every line of code from the course notebook (verbatim).

# --- Code cell 8 ---
square=lambda x:x**2
result=square(5)
result

# --- Code cell 9 ---
square=lambda x,y:x**2
result=square(5)
result

# --- Code cell 10 ---
square=lambda x,y:x**2
result=square(5,6)
result

# --- Code cell 11 ---
square=lambda x,y:x+y
result=square(5,6)
result

# --- Code cell 12 ---
# syntax for map
# map(function,iterable1,iterable2.....)

# --- Code cell 13 ---
numbers=(2,4,6,8)
double_num=list(map(lambda x:x*2,numbers))
print(double_num)

# --- Code cell 14 ---
add=lambda a,b:a+b
add(5,3)

# --- Code cell 16 ---
# Program to show the use of lambda functions
double = lambda x : x ** 2
print(double(5))

# --- Code cell 19 ---
def double(x):
   return x * 2

# --- Code cell 20 ---
double(10)

# --- Code cell 23 ---
# Program to filter out only the even items from a list
my_list = [1, 5, 4, 6, 8, 11, 3, 12]

new_list = tuple(filter(lambda x : (x%2 == 0), my_list))

print(new_list)

# --- Code cell 25 ---
# Program to double each item in a list using map()
my_list1 = [1, 5, 4, 6, 8, 11, 3, 12]

new_list1 = list(map(lambda x : (x * 2), my_list1))

new_list1

# --- Code cell 26 ---
a = [1, 2, 3]
b = [10, 20, 30]
result = list(map(lambda x, y: x + y, a, b))
print(result)

# --- Code cell 27 ---
zip---that combines (or zips) multiple iterables (like lists, tuples, strings, etc.) element by element into tuples.

Think of it as β€œpairing up” items that share the same position.

# --- Code cell 28 ---
names = ['Alice', 'Bob', 'Charlie']
scores = [85, 90, 88,99]

combined = dict(zip(names, scores))
print(combined)

# --- Code cell 29 ---
keys = ['name', 'age', 'name']  # 'name' appears twice
values = ['Alice', 25, 'Bob']

result = dict(zip(keys, values))
print(result)

# --- Code cell 30 ---
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'New York']
result = dict(zip(keys, values))
print(result)