Hello! Welcome to your seventh lesson in the "Python for Data Science: Foundations" module.
In the last lesson, we explored how to import and use modules from Python's standard library, like math and random. You learned how to bring powerful, pre-written code into your programs, saving you time and effort.
Today, we take that concept a step further by diving into one of the most important third-party libraries for any data scientist: NumPy. This lesson directly addresses the learning outcome: Perform array and matrix operations using the NumPy library. NumPy is the bedrock of numerical computing in Python, and mastering it is essential for your journey into data science, machine learning, and for your GATE exam preparation. It forms the foundation for other key libraries, including Pandas, which we'll cover next.
1. What is NumPy and Why is it Essential?
NumPy (short for Numerical Python) is a library that provides a powerful object called an N-dimensional array (or ndarray). Think of it as a highly efficient, supercharged version of a Python list that is optimized for mathematical operations.
Why not just use Python lists?
- Speed: NumPy operations are written in C, a low-level language, which makes them much faster than equivalent operations on Python lists.
- Memory Efficiency: NumPy arrays store data more compactly.
- Convenience: NumPy provides a huge number of built-in functions for linear algebra, statistical analysis, and other mathematical tasks.
As you learned in the previous lesson, we need to import a library to use it. The standard convention, which you will see everywhere in the data science world, is to import NumPy with the alias np.
import numpy as np
From now on, we will use np to access all of NumPy's functions.
2. Creating NumPy Arrays
The most fundamental step is creating a NumPy array. You can create one from a standard Python list.
- A 1D array (or a vector) is created from a simple list.
- A 2D array (or a matrix) is created from a list of lists.
# Create a 1D array (vector)
vec = np.array([1, 2, 3, 4])
print("Vector:")
print(vec)
# Create a 2D array (matrix)
mat = np.array([[1, 2, 3], [4, 5, 6]])
print("\nMatrix:")
print(mat)
The image below illustrates these fundamental structures.

Let's watch a short video segment that demonstrates the basic initialization of these arrays.
Python NumPy Tutorial for Beginners
The 'Python NumPy Tutorial for Beginners' video from freeCodeCamp.org starts by showing exactly how to create 1D and 2D arrays from lists.
Watch from 11:04 to 12:56. Focus on how a Python list is passed to the np.array() function to create both one-dimensional and two-dimensional arrays.
Besides creating arrays from lists, NumPy provides handy functions to create arrays with initial placeholder content. This is very useful when you know the size of the array you need but not the values yet.
np.zeros((rows, cols)): Creates an array of a given shape filled with zeros.np.ones((rows, cols)): Creates an array filled with ones.np.arange(start, stop, step): Creates an array with a range of numbers, similar to Python'srange().
# A 3x4 matrix of zeros
zeros_matrix = np.zeros((3, 4))
print(zeros_matrix)
# A 1D array of five ones
ones_vector = np.ones(5)
print("\n", ones_vector)
# An array of even numbers from 2 up to (but not including) 10
evens = np.arange(2, 10, 2)
print("\n", evens)
3. Inspecting Your Arrays: Shape, Size, and Type
Once you have an array, you'll often need to know its properties. NumPy arrays have several useful attributes:
.shape: A tuple representing the dimensions of the array (e.g.,(2, 3)for a 2x3 matrix)..ndim: The number of dimensions (e.g.,1for a vector,2for a matrix)..size: The total number of elements in the array..dtype: The data type of the elements (e.g.,int64,float64).
The following video segment will walk you through these attributes.
Python NumPy Tutorial for Beginners
Let's return to the freeCodeCamp.org video to see how to check the dimensions, shape, and data type of an array.
Watch from 12:56 to 15:15. Pay attention to the commands a.shape, b.ndim, and a.dtype and what they return.
4. Accessing Elements: Indexing and Slicing
Just like with Python lists, you often need to select specific elements or sections of an array. NumPy uses a similar square bracket [] notation, but with some powerful extensions for multiple dimensions.
For a 2D array (matrix), you use the syntax array[row, column].
- A single number selects that row/column:
mat[0, 1]selects the element in the first row, second column. - A colon
:selects all rows/columns:mat[:, 1]selects all rows from the second column. - A range
start:stopselects a slice:mat[0:2, :]selects the first two rows.

Watching this in action makes it much clearer.
Python NumPy Tutorial for Beginners
The freeCodeCamp.org tutorial provides an excellent walkthrough of indexing and slicing on a 2D array.
Watch from 16:21 to 20:45. Follow along as the instructor gets a specific element, an entire row, an entire column, and then a more complex slice.
Test your understanding!
Given the following matrix:
import numpy as np
A = np.array([[10, 20, 30, 40],
[50, 60, 70, 80],
[90, 100, 110, 120]])
What code would you write to select the subarray [[60, 70], [100, 110]]?
Show answer
The correct code is A[1:3, 1:3].
1:3for the rows selects the rows at index 1 and 2 (the second and third rows).1:3for the columns selects the columns at index 1 and 2 (the second and third columns).
5. Array and Matrix Operations
This is where NumPy truly shines.
Element-wise Operations
Standard arithmetic operators (+, -, *, /) apply the operation element-by-element. If you add two arrays of the same shape, the corresponding elements are added together.
A = np.array([[1, 2], [3, 4]])
B = np.array([[10, 20], [30, 40]])
# Element-wise addition
print(A + B)
# [[11 22]
# [33 44]]
# Element-wise multiplication
print(A * B)
# [[ 10 40]
# [ 90 160]]
You can also perform operations with a single number (a scalar), and NumPy will apply it to every element. This is a concept called broadcasting.
# Add 100 to every element
print(A + 100)
# [[101 102]
# [103 104]]
Matrix Multiplication
This is a crucial concept, especially for your future studies in linear algebra and machine learning. In mathematics, matrix multiplication is different from element-wise multiplication.
In NumPy, the * operator is for element-wise multiplication, NOT matrix multiplication.
To perform true matrix multiplication, you should use the @ operator (or the np.matmul() function).
For two matrices to be multiplied, the number of columns in the first matrix must equal the number of rows in the second.
- A
(2, 3)matrix can be multiplied by a(3, 4)matrix. The result will be a(2, 4)matrix. - A
(2, 3)matrix cannot be multiplied by a(2, 3)matrix.
A = np.array([[1, 2, 3], [4, 5, 6]]) # Shape: (2, 3)
B = np.array([[7, 8], [9, 10], [11, 12]]) # Shape: (3, 2)
# Matrix multiplication
C = A @ B
print(C)
# [[ 58 64]
# [139 154]]
print("Shape of A:", A.shape)
print("Shape of B:", B.shape)
print("Shape of C:", C.shape)
The following video demonstrates both element-wise math and matrix multiplication.
Python NumPy Tutorial for Beginners
This part of the freeCodeCamp video covers both basic arithmetic and matrix multiplication.
Watch from 35:44 to 40:24. First, observe the element-wise operations. Then, pay close attention to the use of np.matmul() for true matrix multiplication and the shape requirements.
For an additional, very clear text explanation of this important difference, please review the following resource.
The CS231n tutorial from Stanford provides a concise and accurate explanation of the difference between element-wise * and matrix multiplication with dot (which is equivalent to @).
Read the section titled 'Array math'. Focus on the code blocks and the paragraph that starts with 'Note that unlike MATLAB, * is elementwise multiplication, not matrix multiplication.'
6. Aggregations and Other Manipulations
NumPy makes it easy to perform aggregations on arrays, like finding the sum, mean, or maximum value.
A = np.array([[1, 2, 3], [4, 5, 6]])
print(A.sum()) # Sum of all elements
print(A.mean()) # Mean of all elements
print(A.min()) # Minimum element
print(A.max()) # Maximum element
A powerful feature is the ability to perform these aggregations along a specific axis.
axis=0collapses the rows and performs the operation down each column.axis=1collapses the columns and performs the operation across each row.
# Sum down the columns (axis=0)
print(A.sum(axis=0)) # [1+4, 2+5, 3+6] -> [5, 7, 9]
# Sum across the rows (axis=1)
print(A.sum(axis=1)) # [1+2+3, 4+5+6] -> [6, 15]
Two other common manipulations are:
- Reshaping: Changing the shape of an array with
.reshape(). The new shape must have the same total number of elements. - Transposing: Flipping a matrix over its diagonal with
.T. This swaps the rows and columns.
A = np.arange(6) # [0, 1, 2, 3, 4, 5]
# Reshape into a 2x3 matrix
B = A.reshape(2, 3)
print(B)
# [[0 1 2]
# [3 4 5]]
# Transpose the matrix
print(B.T)
# [[0 3]
# [1 4]
# [2 5]]
Conclusion
Excellent work! You've just learned the fundamentals of NumPy, the library that powers a huge portion of the data science ecosystem in Python. These skills are not just foundational; they are practical tools you will use constantly.
Key Takeaways:
- NumPy's
ndarrayis a fast and efficient data structure for numerical data. - Arrays are created using
np.array(),np.zeros(),np.arange(), and other functions. - You can access array elements and sections using indexing
[row, col]and slicingstart:stop. - Arithmetic operators (
+,*) perform element-wise operations. - The
@operator performs true matrix multiplication. - Aggregation functions (
.sum(),.mean()) can be applied to the whole array or along a specificaxis. - You can change an array's structure with
.reshape()and.T.
In our next and final lesson for this module, we will learn how to load, manipulate, and analyze data using the Pandas library. You will see that the NumPy arrays and operations you've mastered today are the engine running under the hood of Pandas DataFrames, making this lesson the perfect preparation for working with real-world datasets.