Run in Google Colab
|
View on GitHub
|
NumPy Tutorial¶
This tutorial provides a detailed introduction to NumPy, one of the most widely used libraries for numerical computing in Python. By the end, you should have a good grasp on essential NumPy operations, including array creation, reshaping, indexing, fancy indexing, boolean masking, broadcasting, and random utilities.
Throughout, we’ve added extra explanations and short practice questions to help you test your knowledge. The questions require code-based solutions, so simply uncomment and fill them in as you go.
1. Installation and Import¶
NumPy doesn't come bundled with Python, so you need to install it (unless you’re using a distribution like Anaconda, which comes with NumPy pre-installed). If you set up your Python environment with our previous tutorial, you should already have NumPy installed.
1.1 Install NumPy (if you haven’t already):
pip install numpy
This downloads and installs the NumPy package from the Python Package Index (PyPI).
1.2 Import NumPy:
The as np alias is a common convention that makes it easier to reference NumPy throughout your code.
# Install numpy using pip (ONLY IF NEEDED)
#!pip install numpy
# Importing NumPy
import numpy as np
Why NumPy?
- Efficiency: NumPy arrays are more memory-efficient than Python lists for large-scale data.
- Vectorization: Mathematical operations on arrays are optimized in C, making them very fast.
- Broad Ecosystem: NumPy underpins many other libraries (Pandas, SciPy, TensorFlow, etc.).
2. Creating Arrays¶
NumPy arrays (ndarray objects) are the core data structure for fast numerical computations in Python. They are more efficient than standard Python lists, especially for operations on large datasets.
2.1 From Python Lists¶
You can create a NumPy array simply by passing a Python list to np.array():
arr_list = [1, 2, 3, 4]
arr_np = np.array(arr_list)
print("Created array:", arr_np) # [1 2 3 4]
print("Data type:", arr_np.dtype) # e.g., int64 (depends on platform)
Created array: [1 2 3 4] Data type: int64
2.2 Using Built-in NumPy Functions¶
NumPy provides several functions to generate arrays of specific shapes and values:
np.zeros(shape): Creates an array filled with zeros.np.ones(shape): Creates an array filled with ones.np.full(shape, fill_value): Creates an array filled with a specified value.np.arange(start, stop, step): Creates a range of values from start (inclusive) to stop (exclusive) with a given step.np.linspace(start, stop, num): Creates a set of evenly spaced numbers between start and stop.
zeros_arr = np.zeros(4) # 1D array of 4 zeros
ones_arr = np.ones(5) # 1D array of 5 ones
fours_arr = np.full(6, 4) # 1D array of 6 fours
range_arr = np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
lin_arr = np.linspace(0, 1, 5) # [0., 0.25, 0.5, 0.75, 1.]
print("Zeros array:\n", zeros_arr)
print("Ones array:\n", ones_arr)
print("Fours array:\n", fours_arr)
print("Arange array:", range_arr)
print("Linspace array:", lin_arr)
Zeros array: [0. 0. 0. 0.] Ones array: [1. 1. 1. 1. 1.] Fours array: [4 4 4 4 4 4] Arange array: [0 2 4 6 8] Linspace array: [0. 0.25 0.5 0.75 1. ]
2.3 Array dimensions (shape)¶
Numpy supports multi-dimensional arrays, which are arrays with more than one dimension. For example, a 2D array can be thought of as a matrix with rows and columns, while a 3D array can be thought of as a stack of matrices.
The shape of an array is a tuple that indicates the size of each dimension. For example, a 2D array with 3 rows and 4 columns has a shape of (3, 4). Additionally, you can use array.shape to retrieve the shape of a NumPy array, where array is your NumPy array instance.
a_2d_array = np.array([[1, 2, 3], [4, 5, 6]])
print("2D array:\n", a_2d_array)
print("Shape of 2D array:", a_2d_array.shape) # (2, 3)
a_3d_array = np.array([[[1, 2, 3], [3, 4, 5]], [[5, 6, 7], [7, 8, 9]]])
print("3D array:\n", a_3d_array)
print("Shape of 3D array:", a_3d_array.shape)
2D array: [[1 2 3] [4 5 6]] Shape of 2D array: (2, 3) 3D array: [[[1 2 3] [3 4 5]] [[5 6 7] [7 8 9]]] Shape of 3D array: (2, 2, 3)
Practice Question 1
Without introducing new commands (besides what you’ve seen above), create:
A 1D array of 7 elements, all set to 3.
An array of even numbers from 10 to 20 (exclusive) using
np.arange.Print both arrays to verify.
# Uncomment and complete the code below:
# arr_sevens = ...
# arr_even = ...
# print("Array of sevens:", arr_sevens)
# print("Array of even numbers:", arr_even)
3. Basic Operations¶
NumPy arrays support element-wise arithmetic. This means that when you perform operations on arrays of the same shape, the operation is applied element by element.
x = np.array([1, 2, 3])
y = np.array([10, 20, 30])
print("x + y =", x + y) # [11 22 33]
print("x * 2 =", x * 2) # [2 4 6]
print("x * y =", x * y) # [10 40 90]
x + y = [11 22 33] x * 2 = [2 4 6] x * y = [10 40 90]
Array Statistics
Many functions exist for statistical operations:
mean(),sum(),max(),min(),std()(standard deviation),var()(variance), etc.
arr = np.array([1, 2, 3, 4, 5])
print("Mean:", arr.mean()) # 3.0
print("Sum:", arr.sum()) # 15
print("Max:", arr.max()) # 5
Mean: 3.0 Sum: 15 Max: 5
Practice Question 2
Create a 1D array of
[3, 5, 7, 9]and store it in a variable calledtest_arr.Print out the sum, mean, and standard deviation of
test_arr.Multiply
test_arrby 4 and store it inmultiplied_arr. Printmultiplied_arr.
# Uncomment and complete the code below:
# test_arr = ...
# print("Sum:", ...)
# print("Mean:", ...)
# print("Std Dev:", ...)
# multiplied_arr = ...
# print("multiplied_arr:", multiplied_arr)
mat = np.arange(1, 7) # [1 2 3 4 5 6]
mat_2d = mat.reshape(2, 3)
print("Original array:", mat)
print("Reshaped to 2x3:\n", mat_2d)
Original array: [1 2 3 4 5 6] Reshaped to 2x3: [[1 2 3] [4 5 6]]
4.2 Slicing¶
Slicing in NumPy works similarly to Python lists, but you can do more advanced slicing for multi-dimensional arrays.
arr[start:end]: slices fromstarttoend-1in one dimension.For multi-dimensional arrays:
arr[row_start:row_end, col_start:col_end].
# 1D slicing
arr = np.array([10, 20, 30, 40, 50])
print("arr[1:3] =", arr[1:3]) # [20 30]
arr[1:3] = [20 30]
For 2D arrays we can use two ranges to slice rows and columns. For instance to slice the following 2D array into the highlighted section:
| Index | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 11 | 12 | 13 | 14 |
| 1 | 21 | 22 | 23 | 24 |
| 2 | 31 | 32 | 33 | 34 |
# 2D slicing
array_2d = np.array([[11, 12, 13, 14],
[21, 22, 23, 24],
[31, 32, 33, 34]])
# A slice would be
a_slice = array_2d[:2, 1:3]
print(a_slice)
[[12 13] [22 23]]
You can also use : to slice all rows or columns. For example, arr[1,:] selects all rows and columns 1 and 2.
| Index | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 11 | 12 | 13 | 14 |
| 1 | 21 | 22 | 23 | 24 |
| 2 | 31 | 32 | 33 | 34 |
row_slice = array_2d[1,:]
print(row_slice)
[21 22 23 24]
For slicing whole columns, use arr[:,1]
| Index | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 11 | 12 | 13 | 14 |
| 1 | 21 | 22 | 23 | 24 |
| 2 | 31 | 32 | 33 | 34 |
column_array = array_2d[:, 1]
print(column_array)
[12 22 32]
It is also possible to reverse slices from the end of the array using negative indices.
arr[-1]: last elementarr[-2:]: last two elementsarr[:-1]: all but the last elementarr[-4:-2]: o slice from the end of the array without the last two elementsarr[:,-1]: last column of a 2D array
# 1d advanced slicing
an_array_1d = np.array([10, 20, 30, 40, 50])
print("Last element:", an_array_1d[-1]) # 50
print("Last two elements:", an_array_1d[-2:]) # [40 50]
print("All but the last element:", an_array_1d[:-1]) # [10 20 30 40]
print("Last elements except last two:", an_array_1d[-4:-2]) # [20 30]
print("Last column of 2D array:", array_2d[:,-1]) # [14 24 34]
# 2d array slicing
array_2d = np.array([[11, 12, 13, 14],
[21, 22, 23, 24],
[31, 32, 33, 34]])
print("Last row of 2D array:", array_2d[-1]) # [31 32 33 34]
print("Last two rows of 2D array:\n", array_2d[-2:]) # [[21 22 23 24] [31 32 33 34]]
print("Last two rows and last two columns of 2D array:\n", array_2d[-2:, -2:]) # [[22 23] [32 33]]
Last element: 50 Last two elements: [40 50] All but the last element: [10 20 30 40] Last elements except last two: [20 30] Last column of 2D array: [14 24 34] Last row of 2D array: [31 32 33 34] Last two rows of 2D array: [[21 22 23 24] [31 32 33 34]] Last two rows and last two columns of 2D array: [[23 24] [33 34]]
Practice Question 3
- Create a 1D array of
[5, 10, 15, 20, 25, 30]. Slice out[15, 20, 25]and print it. - Create a 2D array of shape (3,4) using
np.arange(1, 13)(it will contain 1 to 12). Then:- Reshape it to shape (3, 4).
- Print the second row only.
- Print the first two elements of the third row.
- Print the last two columns of the first two rows.
# Uncomment and complete the code below:
# my_arr_1d = np.array([5, 10, 15, 20, 25, 30])
# slice_result = ...
# print("Slice result:", slice_result)
# my_arr_2d = ...
# print(my_arr_2d)
# print("Second row:", ...)
# print("First two elements of third row:", ...)
# print("Last two columns of the first two rows.", ...)
arr = np.array([10, 20, 30, 40, 50])
idx = np.array([0,0,0,1,1,-1]) # positions to pick
print("Fancy indexing result:", arr[idx]) # [30 10 40]
Fancy indexing result: [10 10 10 20 20 50]
5.2 Boolean Masking¶
Boolean masking lets you filter an array based on a condition, returning only the elements that satisfy that condition.
arr = np.array([10, 20, 30, 40, 50])
mask = arr > 25
print("Mask array:", mask) # [False False True True True]
print("Filtered:", arr[mask]) # [30 40 50]
arr[arr < 40]
Mask array: [False False True True True] Filtered: [30 40 50]
array([10, 20, 30])
Practice Question 4
Create an array of
[2, 4, 6, 8, 10, 12]. Use fancy indexing to pick out[10, 4, 2]in that order.Create a boolean mask that selects the elements of this array that are greater than 6.
# Uncomment and complete the code below:
# test_fancy = np.array([2, 4, 6, 8, 10, 12])
# fancy_indices = ...
# print("Fancy selection:", ...)
# print("Elements greater than 6:", ...)
6. Broadcasting¶
Broadcasting describes how NumPy automatically handles arithmetic between arrays of different shapes. When possible, NumPy “broadcasts” the smaller array so that it matches the dimensions of the larger array.
For instance, adding a 1D array to a 2D array along a compatible axis:
a = np.array([[1, 2, 3],
[4, 5, 6]])
b = np.array([10, 20, 30])
print("Result of a + b:\n", a + b)
# The 1D array b is "broadcasted" across each row of a:
Result of a + b: [[11 22 33] [14 25 36]]
Practice Question 5
Create a 2D array
[[1,2],[3,4]].Create a 1D array
[10, 20].Add them using broadcasting and print the result.
(Optional) Predict the shape and values before running the code.
# Uncomment and complete the code below:
# arr_2d = np.array([[1,2],[3,4]])
# arr_1d = np.array([10, 20])
# result_broadcast = ...
# print("Broadcasting result:\n", result_broadcast)
7. Random and Useful Utilities¶
NumPy offers a variety of random number generation functions in the np.random module:
np.random.rand(shape): Uniform distribution over[0, 1).np.random.randn(shape): Normal distribution with mean=0, std=1.np.random.randint(low, high, size): Random integers fromlowtohigh-1.
Inspecting shapes and dimensions:
.shape: Returns the shape (rows, columns)..ndim: Returns the number of dimensions..size: Returns the total number of elements.
# Random numbers
rand_arr = np.random.rand(3, 2) # uniform in [0,1)
randn_arr = np.random.randn(3, 2) # normal distribution (mean=0, std=1)
randint_arr = np.random.randint(5, 15, size=(2,3)) # random ints between 5 and 14
print("Uniform random:\n", rand_arr)
print("Shape:", rand_arr.shape)
print("\nNormal random:\n", randn_arr)
print("Shape:", randn_arr.shape)
print("\nInteger random:\n", randint_arr)
print("Shape:", randint_arr.shape)
Uniform random: [[0.14331159 0.49664192] [0.2732867 0.3803681 ] [0.04899517 0.47154495]] Shape: (3, 2) Normal random: [[ 0.26105074 2.81767613] [-0.04306999 -1.44551721] [-0.64460383 -0.66513559]] Shape: (3, 2) Integer random: [[10 6 6] [12 12 11]] Shape: (2, 3)
Practice Question 6
Generate a 1D array of 5 random integers between 0 and 10.
Print its shape, and number of dimensions.
Reshape it to
(5, 1)and print the new shape.
# Uncomment and complete the code below:
# rand_ints = ...
# print(rand_ints)
# print("Shape of rand_ints:", ...)
# print("Number of dimensions:", ...)
# reshaped = rand_ints.reshape(5,1)
# print("New shape:", reshaped.shape)
# print(reshaped)
Questions¶
Solve the following exercises to practice NumPy basics. Follow the instructions and fill in the blanks where indicated.
There is no need to submit this notebook; it's for your practice only.
1. Array Creation and Initialization¶
Task:
Create a 1D NumPy array of the first 10 positive integers.
Create a 2x5 array of zeros.
Create a 4x4 identity matrix.
# Your solution:
# 1. Create a 1D NumPy array of the first 10 positive integers
# 2. Create a 2x5 array of zeros
# 3. Create a 4x4 identity matrix
2. Array Operations¶
Task:
Given the array arr = np.array([5, 10, 15, 20, 25]), do the following:
Multiply each element by 3.
Subtract 5 from each element.
Compute the sum of all elements in the resulting array.
# Your solution:
arr = np.array([5, 10, 15, 20, 25])
# 1. Multiply each element by 3
# 2. Subtract 5 from each element
# 3. Compute the sum of all elements
3. Reshaping and Indexing¶
Task:
Create a 1D array of integers from 1 to 12.
Reshape it into a 3x4 matrix.
Extract the element in the 2nd row, 3rd column.
Extract the first column as a 1D array.
# Your solution:
# 1. Create a 1D array of integers from 1 to 12
# 2. Reshape it into a 3x4 matrix
# 3. Extract the element in the 2nd row, 3rd column
# 4. Extract the first column as a 1D array
4. Fancy Indexing¶
Task:
Given arr = np.array([100, 200, 300, 400, 500]) and indices = np.array([4, 0, 2]):
Use fancy indexing to extract the elements at positions defined by
indices.Rearrange the extracted elements into descending order.
# Your solution:
arr = np.array([100, 200, 300, 400, 500])
indices = np.array([4, 0, 2])
# 1. Use fancy indexing to extract elements
# 2. Rearrange the extracted elements into descending order
5. Boolean Masking¶
Task:
Given arr = np.array([1, 4, 7, 10, 13, 16]):
Create a boolean mask for elements greater than 8.
Use the mask to extract those elements.
Compute the mean of the extracted elements.
# Your solution:
arr = np.array([1, 4, 7, 10, 13, 16])
# 1. Create a boolean mask for elements greater than 8
# 2. Use the mask to extract those elements
# 3. Compute the mean of the extracted elements
6. Broadcasting¶
Task:
Given the 2D array a = np.array([[1, 2, 3], [4, 5, 6]]):
Add the 1D array
b = np.array([10, 20, 30])to each row ofa.Multiply each element of
aby 2.Compute the sum of all elements in the resulting array.
# Your solution:
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([10, 20, 30])
# 1. Add `b` to each row of `a`
# 2. Multiply each element of `a` by 2
# 3. Compute the sum of all elements
7. Random Array Utilities¶
Task:
Generate a 3x3 array of random values uniformly distributed between 0 and 1.
Generate a 3x3 array of random values drawn from a standard normal distribution.
Compute the mean and standard deviation of each array.
# Your solution:
# 1. Generate a 3x3 array of random values uniformly distributed between 0 and 1
# 2. Generate a 3x3 array of random values drawn from a standard normal distribution
# 3. Compute the mean and standard deviation of each array
Run in Google Colab
View on GitHub