mirror of
https://github.com/Rainyy21/framework_note.git
synced 2026-10-10 23:30:28 -04:00
238 lines
5.8 KiB
Markdown
238 lines
5.8 KiB
Markdown
---
|
|
title: Introduction to NumPy
|
|
tags:
|
|
- python
|
|
- numpy
|
|
- data-science
|
|
- numerical-computing
|
|
category: Lesson
|
|
difficulty: Beginner to Intermediate
|
|
created: 2026-05-26
|
|
---
|
|
|
|
# Introduction to NumPy
|
|
|
|
> [!abstract] What is NumPy?
|
|
> **NumPy** (Numerical Python) is the foundational library for scientific computing in Python. It provides a high-performance multidimensional array object, tools for working with these arrays, and linear algebra, Fourier transform, and random number capabilities.
|
|
>
|
|
> ### Why use NumPy instead of standard Python lists?
|
|
> 1. **Speed:** NumPy arrays are written in C, making mathematical operations up to 100x faster than standard Python lists.
|
|
> 2. **Memory Efficiency:** NumPy arrays use contiguous blocks of memory, whereas Python lists store pointers to objects scattered across memory.
|
|
> 3. **Vectorization:** It allows performing mathematical operations on whole arrays without writing slow `for` loops.
|
|
|
|
---
|
|
|
|
## 📐 The N-Dimensional Array (`ndarray`)
|
|
|
|
The core of NumPy is the **`ndarray`** (N-dimensional array). It is a grid of values, all of the **same type** (homogenous), indexed by a tuple of non-negative integers.
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[ndarray] --> B["1D Array (Vector) <br> Shape: (n,)"]
|
|
A --> C["2D Array (Matrix) <br> Shape: (m, n)"]
|
|
A --> D["3D Array (Tensor) <br> Shape: (p, m, n)"]
|
|
```
|
|
|
|
### Essential Array Attributes
|
|
Every array has attributes that describe its structure:
|
|
|
|
```python
|
|
import numpy as np
|
|
|
|
arr = np.array([[1, 2, 3], [4, 5, 6]])
|
|
|
|
print(arr.ndim) # Number of dimensions (axes) -> 2
|
|
print(arr.shape) # Tuple representing sizes in each dimension -> (2, 3)
|
|
print(arr.size) # Total number of elements -> 6
|
|
print(arr.dtype) # Data type of the elements -> int64
|
|
```
|
|
|
|
---
|
|
|
|
## 🛠️ Creating Arrays
|
|
|
|
First, import the library using the standard alias:
|
|
```python
|
|
import numpy as np
|
|
```
|
|
|
|
### 1. From Python Lists
|
|
```python
|
|
# 1D Vector
|
|
v = np.array([1, 2, 3])
|
|
|
|
# 2D Matrix
|
|
m = np.array([[1, 2], [3, 4]])
|
|
```
|
|
|
|
### 2. Built-in Placeholders
|
|
NumPy provides functions to initialize arrays with placeholders, avoiding manual creation:
|
|
|
|
```python
|
|
# Array of zeros
|
|
zeros = np.zeros((3, 4)) # 3 rows, 4 columns
|
|
|
|
# Array of ones
|
|
ones = np.ones((2, 3), dtype=np.int32)
|
|
|
|
# Range of numbers (similar to range())
|
|
range_arr = np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
|
|
|
|
# Linearly spaced numbers
|
|
linspace_arr = np.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0]
|
|
|
|
# Identity Matrix
|
|
eye_matrix = np.eye(3) # 3x3 identity matrix
|
|
```
|
|
|
|
### 3. Random Number Generation
|
|
```python
|
|
# Uniform random values between [0.0, 1.0)
|
|
rand_arr = np.random.rand(2, 2)
|
|
|
|
# Standard normal distribution (mean=0, std=1)
|
|
randn_arr = np.random.randn(2, 2)
|
|
|
|
# Random integers
|
|
rand_ints = np.random.randint(1, 100, size=(5,))
|
|
```
|
|
|
|
---
|
|
|
|
## ⚡ Element-wise Operations & Vectorization
|
|
|
|
In standard Python, to add two lists element-wise, you need a list comprehension or loop. In NumPy, you do it directly.
|
|
|
|
```python
|
|
x = np.array([1, 2, 3])
|
|
y = np.array([4, 5, 6])
|
|
|
|
print(x + y) # [5, 7, 9]
|
|
print(x * y) # [4, 10, 18]
|
|
print(x ** 2) # [1, 4, 9]
|
|
```
|
|
|
|
### 📡 Broadcasting
|
|
Broadcasting is a powerful mechanism that allows NumPy to perform arithmetic operations on arrays of **different shapes**. The smaller array is "broadcast" across the larger array so that they have compatible shapes.
|
|
|
|
```python
|
|
matrix = np.array([[1, 2, 3], [4, 5, 6]])
|
|
scalar = 10
|
|
|
|
# The scalar is added to every single element
|
|
print(matrix + scalar)
|
|
# [[11, 12, 13]
|
|
# [14, 15, 16]]
|
|
```
|
|
|
|
---
|
|
|
|
## 🔍 Indexing, Slicing & Masking
|
|
|
|
### Slicing 2D Arrays
|
|
Slicing follows the format `array[row_start:row_end, col_start:col_end]`.
|
|
|
|
```python
|
|
arr = np.array([
|
|
[10, 11, 12],
|
|
[20, 21, 22],
|
|
[30, 31, 32]
|
|
])
|
|
|
|
# Get row at index 1
|
|
print(arr[1, :]) # [20, 21, 22]
|
|
|
|
# Get column at index 2
|
|
print(arr[:, 2]) # [12, 22, 32]
|
|
|
|
# Slice a subgrid (top-left 2x2)
|
|
print(arr[0:2, 0:2])
|
|
# [[10, 11]
|
|
# [20, 21]]
|
|
```
|
|
|
|
### 🎭 Boolean Masking (Conditional Filtering)
|
|
You can filter arrays using conditions. NumPy returns elements where the condition resolves to `True`.
|
|
|
|
```python
|
|
data = np.array([1, 5, 8, 12, 3, 15])
|
|
|
|
# Create a boolean mask
|
|
mask = data > 5 # [False, False, True, True, False, True]
|
|
|
|
# Filter using the mask
|
|
filtered_data = data[mask] # [8, 12, 15]
|
|
```
|
|
|
|
---
|
|
|
|
## 🧮 Common Aggregations & Axis Operations
|
|
|
|
Aggregations allow you to compute statistics over entire arrays or along specific **axes**:
|
|
* `axis=0`: Down the columns (collapses rows).
|
|
* `axis=1`: Across the rows (collapses columns).
|
|
|
|
```python
|
|
arr = np.array([[1, 2], [3, 4]])
|
|
|
|
# Sum of all elements
|
|
print(np.sum(arr)) # 10
|
|
|
|
# Sum down the columns (vertical)
|
|
print(np.sum(arr, axis=0)) # [4, 6]
|
|
|
|
# Sum across the rows (horizontal)
|
|
print(np.sum(arr, axis=1)) # [3, 7]
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 Reshaping and Transposing
|
|
|
|
You can change the shape of an array without changing its data using `.reshape()` or `.T` (Transpose).
|
|
|
|
```python
|
|
flat = np.arange(1, 7) # [1, 2, 3, 4, 5, 6]
|
|
|
|
# Reshape into a 2x3 matrix
|
|
matrix = flat.reshape(2, 3)
|
|
# [[1, 2, 3]
|
|
# [4, 5, 6]]
|
|
|
|
# Transpose matrix (swap rows and columns)
|
|
transposed = matrix.T
|
|
# [[1, 4]
|
|
# [2, 5]
|
|
# [3, 6]]
|
|
```
|
|
|
|
---
|
|
|
|
## 💡 Best Practices
|
|
|
|
> [!important] Avoid Standard Loops
|
|
> Standard loops in Python are interpreted, which adds massive overhead. Vectorized operations execute in compiled C, taking advantage of CPU caches and SIMD instructions.
|
|
>
|
|
> **Example Comparison:**
|
|
> ```python
|
|
> # ❌ Extremely Slow
|
|
> values = np.random.rand(1_000_000)
|
|
> reciprocal = [1 / x for x in values]
|
|
>
|
|
> # ✅ Near Instantaneous
|
|
> reciprocal = 1 / values
|
|
> ```
|
|
|
|
> [!tip] Use In-place Operations to Save Memory
|
|
> Instead of creating a new copy, perform calculations directly on the existing array if possible using syntax like `+=`, `-=`, or `*=`.
|
|
> ```python
|
|
> a = np.ones(1000000)
|
|
> b = np.ones(1000000)
|
|
>
|
|
> # Allocates new memory
|
|
> a = a + b
|
|
>
|
|
> # Modifies 'a' in-place (saves memory allocation time)
|
|
> a += b
|
|
> ```
|