Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 13

NumPy Array Operations

Recommended resources

Introduction

Welcome back! In the previous lesson, you built a strong foundation in NumPy by learning how to create, index, slice, and reshape ndarrays. You now understand the structure of these powerful arrays and how to access and organize the data within them. This mastery of data manipulation is the first step.

Today, we move to data computation. This lesson focuses on the learning outcome: Perform element-wise and matrix operations on NumPy arrays. We will explore the two fundamental ways NumPy performs calculations: one-on-one operations across corresponding elements, and the more complex, rule-based operations of linear algebra.

For your goal of building advanced AI, this is a critical step. The complex algorithms that power machine learning models are, at their core, a series of highly optimized mathematical operations on large arrays of data. Today, you'll learn the "verbs" of that mathematical language.


1. Element-Wise Operations

The most common type of operation in NumPy is an element-wise operation. This means that for two arrays of the same shape, an operation is applied to each pair of corresponding elements to produce a new array of the same shape.

Let's start with the basic arithmetic operators: +, -, *, /.

import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[10, 20], [30, 40]])




# Element-wise addition
print("Addition:\n", a + b)




# Element-wise subtraction
print("\nSubtraction:\n", a - b)

Now, let's focus on multiplication. It is crucial to understand that the standard * operator in NumPy performs element-wise multiplication, not matrix multiplication.

NumPy Element-Wise Product Illustration
This image illustrates element-wise multiplication. Each element in the first matrix is multiplied by the element in the corresponding position in the second matrix to produce the final result.

This concept is fundamental. To dive deeper, the following text provides excellent examples and clarifies the performance benefits of these "vectorized" operations over standard Python loops.

NumPy Fundamentals for Data Science and Machine Learning

Let's read a short section from the "NumPy Fundamentals" article. It clearly explains how basic arithmetic operations are performed element-wise and contrasts this with scalar multiplication.

Read the subsection titled "Array arithmetic". Pay close attention to the code examples for addition, subtraction, multiplication, and division. Notice how the operations work on each element independently.

Broadcasting: Operations with Mismatched Shapes

What happens if you try to perform an operation on arrays with different shapes? In the last lesson, we saw that for indexing and assignment, this could lead to errors. However, for arithmetic operations, NumPy has a powerful mechanism called broadcasting.

Broadcasting allows NumPy to perform operations on arrays of different (but compatible) shapes. The most common case is operating on an array with a single number (a scalar).

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




# Multiply every element in 'a' by 10
result = a * 10
print(result)

Output:

[[10 20 30]
 [40 50 60]]

Conceptually, NumPy "stretches" or "duplicates" the scalar 10 to create an array [[10, 10, 10], [40, 50, 60]] so that it can perform an element-wise operation. This is done without actually using extra memory, making it highly efficient.

The "Scipy lecture notes" provide a fantastic visual and a practical example of how this works.

Numerical operations on arrays — Scipy lecture notes

This resource provides a very clear explanation of broadcasting with helpful diagrams.

Read the section "Broadcasting". Focus on the diagram that shows a (4,3) array being added to a (1,3) array. This visualizes how the smaller array is 'stretched' to match the larger one. Also, note the useful trick of using np.newaxis to make arrays compatible for broadcasting.

Broadcasting has a specific set of rules, but the key idea is that dimensions are compared from right to left, and they must either be equal, or one of them must be 1.


2. Matrix Multiplication

While element-wise multiplication is useful, the foundation of linear algebra and most machine learning algorithms is matrix multiplication, also known as the dot product.

Given your BTech background, you'll likely recall the rule for matrix multiplication: to multiply matrix A by matrix B, the number of columns in A must equal the number of rows in B.
If A has shape and B has shape , their product C will have shape .

In NumPy, you can perform matrix multiplication in two ways:

  1. The np.dot() function: np.dot(A, B)
  2. The @ operator: A @ B (This is the modern, preferred syntax)

Let's watch a video that breaks this down. It first reviews element-wise multiplication, then provides an excellent visual walkthrough of how matrix multiplication is calculated, before finally showing the Python code.

Multiplication of Matrix Using Numpy - Python Tutorial

This video from DataMites clearly distinguishes element-wise from matrix multiplication and provides a step-by-step visual explanation of the dot product calculation.

Watch from 01:54 to 07:13. The first part (until 02:38) reinforces the concept of element-wise multiplication using the * operator. The core of the clip (02:38 to 06:10) provides a manual, visual calculation of a dot product. This aligns perfectly with your theory-first preference. The final part (from 06:10) shows you how to implement this easily with np.dot() and np.matmul() (which is equivalent to the @ operator).


3. Other Essential Matrix Operations

Besides multiplication, there are a few other operations that are fundamental to linear algebra and data science.

Transpose

The transpose of a matrix flips it over its diagonal. It switches the row and column indices. A matrix with shape (m, n) becomes a matrix with shape (n, m). This is often used to make matrix dimensions compatible for multiplication. In NumPy, you can get the transpose using the .T attribute.

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

print("Original A (shape", A.shape, "):\n", A)
print("\nTranspose of A (shape", A.T.shape, "):\n", A.T)

Inverse

The inverse of a square matrix , denoted , is a matrix such that when multiplied by , it results in the identity matrix (a matrix of ones on the diagonal and zeros elsewhere).

Finding the inverse is crucial for solving systems of linear equations. You can compute it using np.linalg.inv().

To see a quick demonstration of these operations in code, let's watch two short clips.

Python Tutorial: Matrix Operations using Numpy for Absolute Beginners

This video from Mr. STEM EDU TV provides quick, clear demonstrations of finding the inverse and transpose of a matrix.

First, watch from 05:32 to 06:10 to see how np.linalg.inv() is used to find the inverse and verify the result. Then, watch from 07:07 to 07:32 to see how to transpose a matrix with np.transpose() (which is the same as the .T attribute).

Note: Not all matrices have an inverse. A matrix that does not have an inverse is called a singular or degenerate matrix. Trying to compute the inverse of a singular matrix will result in a LinAlgError.


Your Turn: Practice Exercise

Time to apply these concepts. This exercise will challenge you to distinguish between element-wise and matrix operations and use the correct syntax for each.

Task (5-10 minutes):

  1. Create a 2x3 NumPy array A with values from 1 to 6.
  2. Create a 3x2 NumPy array B with values from 7 to 12.
  3. Calculate the matrix product of A and B, storing the result in a new array C. Print C and its shape.
  4. Try to compute the element-wise product of A and B (A * B). This will fail. In a comment, briefly explain why.
  5. Calculate the matrix product of B and A, storing it in D. Is D the same as C? This demonstrates that matrix multiplication is not commutative.
  6. Create a new 2x2 array E with random integer values between 1 and 5.
  7. Compute the element-wise product of C and E.
Click to see a possible solution
import numpy as np




# 1. Create array A
A = np.arange(1, 7).reshape(2, 3)
print("A:\n", A)




# 2. Create array B
B = np.arange(7, 13).reshape(3, 2)
print("\nB:\n", B)




# 3. Calculate matrix product C = A @ B
C = A @ B
print("\nC (A @ B):\n", C)
print("Shape of C:", C.shape)




# 4. Attempt element-wise product
# A * B 
# This fails because element-wise operations require the arrays to have the same shape.
# A has shape (2, 3) and B has shape (3, 2), so they are not compatible for a '*' operation.




# 5. Calculate matrix product D = B @ A
D = B @ A
print("\nD (B @ A):\n", D)
print("Is C equal to D?", np.array_equal(C, D)) # Will be False




# 6. Create random array E
E = np.random.randint(1, 6, size=(2, 2))
print("\nE:\n", E)




# 7. Compute element-wise product of C and E
result = C * E
print("\nElement-wise product of C and E:\n", result)

Conclusion

Excellent work. You have now learned how to perform the fundamental computations that drive numerical analysis and machine learning in Python.

Key Takeaways:

  • Element-wise operations (+, -, *, /) apply an operation to corresponding elements in arrays of the same shape.
  • The * operator performs element-wise multiplication, not matrix multiplication.
  • Broadcasting is NumPy's mechanism for performing operations on arrays of different but compatible shapes, like an array and a scalar.
  • Matrix multiplication (dot product) follows the rules of linear algebra and is performed using the @ operator or np.dot(). The dimensions must be compatible (m, n) @ (n, p).
  • Other key operations include finding the transpose (.T) and inverse (np.linalg.inv()) of a matrix.

Preview of the Next Lesson:
So far, we've worked with NumPy's powerful but somewhat abstract ndarray. Real-world data, however, is often messy and comes with labels, like column headers in a spreadsheet. In the next lesson, "Load, inspect, and select data in pandas DataFrames", we will introduce the pandas library. Pandas is built on top of NumPy and provides a data structure called a DataFrame, which is perfectly designed for handling the structured, tabular data you'll encounter in almost every AI project.