Now that you know how to create NumPy arrays and access their elements, let's explore one of the most powerful features of NumPy: performing fast, element-wise mathematical operations. Unlike standard Python lists, where you would typically need to loop through elements to perform arithmetic, NumPy allows you to apply operations directly to entire arrays at once. This approach is not only more concise but also significantly faster, especially for large arrays, because these operations are implemented in highly optimized, low-level code (often C or Fortran).
You can use standard Python arithmetic operators directly with NumPy arrays. These operations are applied element by element.
If you perform an operation between two arrays, NumPy pairs up corresponding elements and performs the calculation for each pair. For this to work directly, the arrays involved usually need to have the same shape.
Let's create two simple arrays to work with:
import numpy as np
# Create two arrays with the same shape
array_a = np.array([1, 2, 3, 4])
array_b = np.array([10, 20, 30, 40])
print("Array A:", array_a)
print("Array B:", array_b)
Output:
Array A: [1 2 3 4]
Array B: [10 20 30 40]
Now, let's perform some basic operations:
Addition (+
)
Adds corresponding elements from array_a
and array_b
.
# Element-wise addition
sum_array = array_a + array_b
print("Addition (A + B):", sum_array)
Output:
Addition (A + B): [11 22 33 44]
Explanation: 1+10=11, 2+20=22, 3+30=33, 4+40=44.
Subtraction (-
)
Subtracts elements of array_b
from the corresponding elements of array_a
.
# Element-wise subtraction
diff_array = array_a - array_b
print("Subtraction (A - B):", diff_array)
Output:
Subtraction (A - B): [ -9 -18 -27 -36]
Explanation: 1−10=−9, 2−20=−18, 3−30=−27, 4−40=−36.
Multiplication (*
)
Multiplies corresponding elements. Note that this is element-wise multiplication, not matrix multiplication (which we'll cover later).
# Element-wise multiplication
prod_array = array_a * array_b
print("Multiplication (A * B):", prod_array)
Output:
Multiplication (A * B): [ 10 40 90 160]
Explanation: 1×10=10, 2×20=40, 3×30=90, 4×40=160.
Division (/
)
Divides elements of array_a
by the corresponding elements of array_b
.
# Element-wise division
div_array = array_a / array_b
print("Division (A / B):", div_array)
Output:
Division (A / B): [0.1 0.1 0.1 0.1]
Explanation: 1/10=0.1, 2/20=0.1, 3/30=0.1, 4/40=0.1.
These operations also work for multi-dimensional arrays, as long as their shapes match:
# Example with 2D arrays
matrix_c = np.array([[1, 2], [3, 4]])
matrix_d = np.array([[10, 20], [30, 40]])
print("\nMatrix C:\n", matrix_c)
print("Matrix D:\n", matrix_d)
sum_matrix = matrix_c + matrix_d
print("\nAddition (C + D):\n", sum_matrix)
Output:
Matrix C:
[[1 2]
[3 4]]
Matrix D:
[[10 20]
[30 40]]
Addition (C + D):
[[11 22]
[33 44]]
You can also perform arithmetic operations between a NumPy array and a single number (a scalar). NumPy efficiently applies this operation to every element in the array. This is a simple example of a concept called broadcasting, where NumPy implicitly expands the scalar to match the array's shape.
Let's use array_a
again: [1 2 3 4]
Adding a Scalar
# Add 5 to every element
add_scalar = array_a + 5
print("Add 5:", add_scalar)
Output:
Add 5: [6 7 8 9]
Explanation: 1+5=6, 2+5=7, 3+5=8, 4+5=9.
Multiplying by a Scalar
# Multiply every element by 10
mul_scalar = array_a * 10
print("Multiply by 10:", mul_scalar)
Output:
Multiply by 10: [10 20 30 40]
Explanation: 1×10=10, 2×10=20, 3×10=30, 4×10=40.
Exponentiation (**
)
Raise every element to a power.
# Square every element
pow_scalar = array_a ** 2
print("Square elements:", pow_scalar)
Output:
Square elements: [ 1 4 9 16]
Explanation: 12=1, 22=4, 32=9, 42=16.
NumPy supports other standard arithmetic operations element-wise as well:
//
): Performs division and rounds the result down to the nearest whole number (integer).%
): Returns the remainder of a division.# Use array_a = [1 2 3 4] and array_e = [2 2 2 2]
array_e = np.array([2, 2, 2, 2])
floor_div = array_a // array_e
print("Floor Division (A // E):", floor_div)
modulo = array_a % array_e
print("Modulo (A % E):", modulo)
# Example with scalar
floor_div_scalar = array_b // 15 # array_b = [10 20 30 40]
print("Floor Division (B // 15):", floor_div_scalar)
Output:
Floor Division (A // E): [0 1 1 2]
Modulo (A % E): [1 0 1 0]
Floor Division (B // 15): [0 1 2 2]
Behind the scenes, these arithmetic operators are often shortcuts for NumPy's Universal Functions (ufuncs). For instance, array_a + array_b
is equivalent to calling np.add(array_a, array_b)
. While using the operators (+
, -
, *
, /
) is common for basic arithmetic due to readability, you might encounter these function forms (np.add
, np.subtract
, np.multiply
, np.divide
, np.power
, etc.) as well. NumPy provides a vast library of ufuncs for mathematical, trigonometric, statistical, and other operations that work efficiently on arrays.
These basic arithmetic operations form the building blocks for many numerical computations you'll perform in linear algebra and machine learning. Being comfortable with applying these operations element-wise to NumPy arrays is fundamental for implementing more complex algorithms later on.
© 2025 ApX Machine Learning