NumPy Element-wise Operations

numpy
Published

March 28, 2024

What are Element-wise Operations?

Element-wise operations apply a given function or operation to each element of an array independently. This contrasts with matrix operations (like matrix multiplication), which involve more complex interactions between elements. In NumPy, most standard arithmetic operators (+, -, *, /, //, %, **) and many mathematical functions are designed to work element-wise on arrays.

Basic Arithmetic Operations

Let’s start with the simplest examples: adding, subtracting, multiplying, and dividing arrays. Assume we have two NumPy arrays:

import numpy as np

arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])

Performing element-wise addition:

result_add = arr1 + arr2  # Output: [ 6  8 10 12]
print(result_add)

Subtraction, multiplication, and division follow the same pattern:

result_sub = arr1 - arr2  # Output: [-4 -4 -4 -4]
result_mul = arr1 * arr2  # Output: [ 5 12 21 32]
result_div = arr1 / arr2  # Output: [0.2        0.33333333 0.42857143 0.5       ]
print(result_sub, result_mul, result_div)

Beyond Basic Arithmetic: More Advanced Operations

NumPy’s element-wise capabilities extend far beyond basic arithmetic. Let’s explore some more advanced examples:

Exponentiation:

arr_exp = np.array([1, 2, 3])
result_exp = arr_exp ** 2 # Output: [1 4 9]
print(result_exp)

Using NumPy’s Universal Functions (ufuncs):

NumPy’s ufuncs provide highly optimized functions for element-wise operations. These include trigonometric functions, logarithms, exponentials, and more.

arr_trig = np.array([0, np.pi/2, np.pi])
sin_arr = np.sin(arr_trig) # Output: [0.0000000e+00 1.0000000e+00 1.2246468e-16]
cos_arr = np.cos(arr_trig) # Output: [ 1.00000000e+00 -1.83697020e-16 -1.00000000e+00]
print(sin_arr, cos_arr)

Comparisons:

Element-wise comparisons are also supported, resulting in Boolean arrays:

arr_comp1 = np.array([1, 2, 3])
arr_comp2 = np.array([3, 2, 1])
comparison = arr_comp1 > arr_comp2 # Output: [False False  True]
print(comparison)

Combining Element-wise Operations:

You can chain multiple element-wise operations together in a single expression:

arr_combined = np.array([1, 2, 3, 4])
result_combined = (arr_combined * 2) + 5  # Output: [ 7  9 11 13]
print(result_combined)

Broadcasting

NumPy’s broadcasting allows operations between arrays of different shapes under certain conditions. For instance, adding a scalar (single number) to an array:

arr_broadcast = np.array([1,2,3])
result_broadcast = arr_broadcast + 5 #Output: [6 7 8]
print(result_broadcast)

Broadcasting rules can be more complex with arrays of higher dimensions, but the fundamental principle remains: NumPy attempts to stretch smaller arrays to match the shape of larger arrays before performing the element-wise operation. This greatly simplifies code and enhances efficiency.