### 1.
Array Creation
#### 1.1 Creating Arrays from Lists
You can create NumPy arrays from Python lists.
```python
import numpy as np
# 1D array
arr1 = np.array([1, 2, 3, 4])
print(arr1) # Output: [1 2 3 4]
# 2D array
arr2 = np.array([[1, 2], [3, 4]])
print(arr2)
# Output:
# [[1 2]
# [3 4]]
```
#### 1.2 Creating Arrays with Zeros, Ones, and Empty
These functions create arrays filled with zeros, ones, or uninitialized values.
```python
# Array of zeros
zeros_arr = np.zeros((3, 3))
print(zeros_arr)
# Output:
# [[0. 0. 0.]
# [0. 0. 0.]
# [0. 0. 0.]]
# Array of ones
ones_arr = np.ones((2, 4))
print(ones_arr)
# Output:
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# Uninitialized array (empty)
empty_arr = np.empty((2, 3))
print(empty_arr)
# Output:
# [[0. 0. 0.]
# [0. 0. 0.]]
```
#### 1.3 Creating Arrays with arange and linspace
`arange` creates arrays with a specified range, while `linspace` creates arrays with a specified
number of evenly spaced values.
```python
# Using arange
arr3 = np.arange(0, 10, 2)
print(arr3) # Output: [0 2 4 6 8]
# Using linspace
arr4 = np.linspace(0, 1, 5)
print(arr4) # Output: [0. 0.25 0.5 0.75 1. ]
```
#### 1.4 Identity and Diagonal Arrays
```python
# Identity matrix
identity_matrix = np.identity(3)
print(identity_matrix)
# Output:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
# Diagonal matrix
diagonal_matrix = np.diag([1, 2, 3])
print(diagonal_matrix)
# Output:
# [[1 0 0]
# [0 2 0]
# [0 0 3]]
```
### 2. Array Attributes and Methods
#### 2.1 Shape and Size
Retrieve the shape and size of an array.
```python
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.shape) # Output: (2, 3)
print(arr.size) # Output: 6
print(arr.ndim) # Output: 2 (number of dimensions)
```
#### 2.2 Data Type
Determine the data type of array elements.
```python
print(arr.dtype) # Output: int64 (or int32 depending on the platform)
```
#### 2.3 Reshaping and Flattening
Change the shape of an array and flatten it.
```python
reshaped_arr = arr.reshape(3, 2)
print(reshaped_arr)
# Output:
# [[1 2]
# [3 4]
# [5 6]]
flattened_arr = arr.flatten()
print(flattened_arr) # Output: [1 2 3 4 5 6]
```
### 3. Basic Array Operations
#### 3.1 Element-wise Operations
Perform operations like addition, subtraction, multiplication, and division on arrays.
```python
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
# Addition
print(arr1 + arr2) # Output: [5 7 9]
# Subtraction
print(arr1 - arr2) # Output: [-3 -3 -3]
# Multiplication
print(arr1 * arr2) # Output: [ 4 10 18]
# Division
print(arr1 / arr2) # Output: [0.25 0.4 0.5 ]
```
#### 3.2 Scalar Operations
Operations with a scalar.
```python
# Scalar multiplication
print(arr1 * 2) # Output: [2 4 6]
# Scalar addition
print(arr1 + 1) # Output: [2 3 4]
```
#### 3.3 Universal Functions (ufuncs)
NumPy provides many universal functions for element-wise operations.
```python
# Square root
print(np.sqrt(arr1)) # Output: [1. 1.41421356 1.73205081]
# Exponential
print(np.exp(arr1)) # Output: [ 2.71828183 7.3890561 20.08553692]
# Sine
print(np.sin(arr1)) # Output: [0.84147098 0.90929743 0.14112001]
```
### 4. Statistical and Mathematical Functions
#### 4.1 Basic Statistics
Compute statistics like sum, mean, median, and standard deviation.
```python
arr = np.array([1, 2, 3, 4, 5])
# Sum
print(np.sum(arr)) # Output: 15
# Mean
print(np.mean(arr)) # Output: 3.0
# Median
print(np.median(arr)) # Output: 3.0
# Standard deviation
print(np.std(arr)) # Output: 1.4142135623730951
```
#### 4.2 Minimum and Maximum
Find the minimum and maximum values.
```python
print(np.min(arr)) # Output: 1
print(np.max(arr)) # Output: 5
# Index of minimum and maximum
print(np.argmin(arr)) # Output: 0
print(np.argmax(arr)) # Output: 4
```
### 5. Broadcasting and Vectorization
#### 5.1 Broadcasting
Broadcasting allows operations on arrays of different shapes.
```python
arr = np.array([[1, 2, 3], [4, 5, 6]])
scalar = 2
print(arr + scalar)
# Output:
# [[3 4 5]
# [6 7 8]]
```
#### 5.2 Vectorization
Vectorization refers to performing operations without explicit loops, making computations faster.
```python
arr = np.array([1, 2, 3])
vectorized_result = arr * arr # Element-wise multiplication
print(vectorized_result) # Output: [1 4 9]
```
### 6. Linear Algebra Operations
#### 6.1 Dot Product
Compute the dot product of two arrays.
```python
arr1 = np.array([1, 2])
arr2 = np.array([3, 4])
dot_product = np.dot(arr1, arr2)
print(dot_product) # Output: 11
```
#### 6.2 Matrix Multiplication
Perform matrix multiplication.
```python
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
matrix_product = np.matmul(arr1, arr2)
print(matrix_product)
# Output:
# [[19 22]
# [43 50]]
```
#### 6.3 Inverse and Transpose
Compute the inverse and transpose of a matrix.
```python
matrix = np.array([[1, 2], [3, 4]])
# Transpose
transpose = np.transpose(matrix)
print(transpose)
# Output:
# [[1 3]
# [2 4]]
# Inverse
inverse = np.linalg.inv(matrix)
print(inverse)
# Output:
# [[-2. 1. ]
# [ 1.5 -0.5]]
```
### 7. Indexing and Slicing
#### 7.1 Basic Indexing
Access specific elements, rows, and columns.
```python
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Element access
print(arr[0, 1]) # Output: 2
# Row access
print(arr[1, :]) # Output: [4 5 6]
# Column access
print(arr[:, 2]) # Output: [3 6 9]
```
#### 7.2 Slicing
Extract subarrays using slicing.
```python
# Slicing rows and columns
print(arr[0:2, 1:3])
# Output:
# [[2 3]
# [5 6]]
# Reverse slicing
print(arr[::-1, ::-
1])
# Output:
# [[9 8 7]
# [6 5 4]
# [3 2 1]]
```
### 8. Advanced Array Manipulation
#### 8.1 Concatenation and Stacking
Join arrays along different axes.
```python
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6]])
# Concatenate along rows
concatenated = np.concatenate((arr1, arr2), axis=0)
print(concatenated)
# Output:
# [[1 2]
# [3 4]
# [5 6]]
# Stack along columns
stacked = np.hstack((arr1, arr2.T))
print(stacked)
# Output:
# [[1 2 5]
# [3 4 6]]
```
#### 8.2 Splitting
Split arrays into multiple sub-arrays.
```python
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Split into three sub-arrays
split_arr = np.split(arr, 3)
for subarr in split_arr:
print(subarr)
# Output:
# [[1 2 3]]
# [[4 5 6]]
# [[7 8 9]]
```
#### 8.3 Broadcasting and Vectorization
Utilize broadcasting to apply operations to arrays of different shapes.
```python
arr = np.array([[1, 2, 3], [4, 5, 6]])
scalar = 2
print(arr * scalar)
# Output:
# [[ 2 4 6]
# [ 8 10 12]]
```
### 9. Boolean Indexing and Advanced Indexing
#### 9.1 Boolean Indexing
Filter arrays using boolean conditions.
```python
arr = np.array([1, 2, 3, 4, 5])
# Boolean condition
bool_arr = arr > 2
print(bool_arr) # Output: [False False True True True]
# Filtered array
filtered_arr = arr[bool_arr]
print(filtered_arr) # Output: [3 4 5]
```
#### 9.2 Fancy Indexing
Select elements using arrays of indices.
```python
arr = np.array([10, 20, 30, 40, 50])
# Indexing with an array
indices = [1, 3, 4]
print(arr[indices]) # Output: [20 40 50]
```
### 10. Handling Missing Data
#### 10.1 NaN Handling
Use `numpy.nan` and related functions to handle missing data.
```python
arr = np.array([1, np.nan, 3, 4])
# Check for NaNs
print(np.isnan(arr)) # Output: [False True False False]
# Replace NaNs with a specific value
clean_arr = np.nan_to_num(arr, nan=0)
print(clean_arr) # Output: [1. 0. 3. 4.]
```
### 11. Saving and Loading Data
#### 11.1 Save and Load Arrays
Save arrays to and load arrays from files.
```python
arr = np.array([1, 2, 3])
# Save array to a file
np.save('array.npy', arr)
# Load array from a file
loaded_arr = np.load('array.npy')
print(loaded_arr) # Output: [1 2 3]
```
### 12. Random Number Generation
#### 12.1 Generating Random Numbers
Use NumPy's random module to generate random numbers.
```python
# Random integers
rand_ints = np.random.randint(0, 10, size=(3, 3))
print(rand_ints)
# Output: A 3x3 array of random integers between 0 and 9
# Random floats
rand_floats = np.random.random((2, 3))
print(rand_floats)
# Output: A 2x3 array of random floats between 0 and 1
```
### 13. Sorting and Searching
#### 13.1 Sorting Arrays
Sort arrays along specified axes.
```python
arr = np.array([3, 1, 2])
sorted_arr = np.sort(arr)
print(sorted_arr) # Output: [1 2 3]
# Sort along rows or columns in a 2D array
arr_2d = np.array([[3, 2, 1], [6, 5, 4]])
sorted_2d = np.sort(arr_2d, axis=1)
print(sorted_2d)
# Output:
# [[1 2 3]
# [4 5 6]]
```
#### 13.2 Searching and Extracting Elements
Find elements and their indices.
```python
arr = np.array([1, 2, 3, 4, 5])
# Find index of a value
index = np.where(arr == 3)
print(index) # Output: (array([2]),)
# Extract elements based on a condition
extracted_elements = arr[arr > 2]
print(extracted_elements) # Output: [3 4 5]
```