NumPy Arrays
On this page
The NumPy array, formally called an ndarray (n-dimensional array), is the heart of NumPy. It’s similar to a Python list, but far more powerful because it stores all elements of the same type in a highly optimized structure designed for fast numerical operations.
One-dimensional arrays (vectors)
A one-dimensional array in NumPy represents a simple, ordered list of values. In mathematics, this is called a vector (). A vector is often shown as an arrow that points from one place to another. It has two important ideas:
- Magnitude — how long the arrow is, noted .
- Direction — which way the arrow points.
For example, a vector can be written as:
where x and y describe how far the arrow goes horizontally and vertically. If the arrow goes 3 units to the right and 4 units up, the vector is .
import matplotlib.pyplot as plt
import numpy as np
# Define the vector components
x = 3
y = 4
# Compute the magnitude using the Pythagorean theorem
magnitude = np.sqrt(x**2 + y**2)
# Create the figure
plt.figure(figsize=(6, 6))
# Plot the vector from the origin (0,0) to (x,y)
plt.quiver(0, 0, x, y, angles='xy', scale_units='xy', scale=1,
color='navy', linewidth=2.5, label=f"v({x}, {y})")
# Draw the triangle sides (projection on x and y axes)
plt.plot([0, x], [0, 0], 'r--', linewidth=1) # base along x-axis
plt.plot([x, x], [0, y], 'r--', linewidth=1) # height along y-axis
# Annotate the magnitude on the hypotenuse
plt.text(x/2, y/2, f"Magnitude = {magnitude:.1f}", fontsize=12, color='darkgreen',
ha='center', va='bottom', fontweight='bold')
# Annotate vector endpoint
plt.text(x + 0.2, y, f"v({x}, {y})", fontsize=12, color='black')
# Set axis limits and labels
plt.xlim(0, 5.5)
plt.ylim(0, 5.5)
plt.axhline(0, color='black', linewidth=1)
plt.axvline(0, color='black', linewidth=1)
plt.xlabel("x-axis (horizontal distance)")
plt.ylabel("y-axis (vertical distance)")
plt.title("Vector v(3,4) with Magnitude and Components")
# Keep the aspect ratio equal for accurate geometry
plt.gca().set_aspect('equal', 'box')
plt.legend()
plt.grid(True)
plt.show()The magnitude (or length) of this vector is found using the Pythagorean theorem:
For , the length is:
The direction of a vector shows where it points.
If we divide the vector by its length, we get another vector pointing the same way, but with length 1.
This is called the unit vector:
NumPy stores vectors in arrays so that they can be used for calculation and comparison more easily.
For example:
my_list = [1, 2, 3]
np_array = np.array(my_list)
print(np_array)[1 2 3]
This creates a one-dimensional array containing the numbers 1, 2, and 3. Each number in this array can represent something meaningful: the number of books an author published in three different years, or the average sentiment scores of three literary reviews.
In data analysis, vectors are used whenever we need to store and process a sequence of related values — such as population counts over time, yearly rainfall data, or the frequency of a specific word across different texts. Because all elements in a NumPy vector share the same data type, mathematical operations like addition or scaling apply to the entire sequence efficiently.
The example below shows two vectors that record the number of books published by two authors across five decades. By plotting these vectors, it becomes easy to see how their publication patterns changed over time.
import numpy as np
import matplotlib.pyplot as plt
# Define the decades and publication counts for two authors
decades = np.array([1980, 1990, 2000, 2010, 2020])
author_a = np.array([2, 5, 3, 6, 7]) # Author A: varied output
author_b = np.array([1, 3, 5, 6, 5]) # Author B: steady rise, small drop
# Plot the publication trends
plt.figure(figsize=(8, 5))
plt.plot(decades, author_a, marker='o', linewidth=2, label="Author A")
plt.plot(decades, author_b, marker='s', linewidth=2, label="Author B")
# Add titles and labels
plt.title("Book Publications by Two Authors (1980–2020)")
plt.xlabel("Decade")
plt.ylabel("Number of Books Published")
# Add grid, legend, and display
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.show()This plot shows two lines that represent the two vectors. Each point on the lines corresponds to one value in the arrays. The lines reveal how publication numbers changed across decades: Author A’s output rose, dipped around 2000, and then increased again, while Author B’s output followed a steady upward trend before a small drop. Such patterns help to compare data series over time, a common task in data analysis and the digital humanities.
Multidimensional arrays (matrices)
A multidimensional array in NumPy is an array that has more than one axis or dimension. The most common example is the two-dimensional array, which can be thought of as a grid of numbers arranged in rows and columns.
In Python and NumPy, such arrays are often used to store data that naturally fits into a table — for example, numerical results, images, or datasets where each row represents an observation and each column represents a variable.
Let’s look at a simple example:
import numpy as np
my_matrix = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(my_matrix)[[1 2 3]
[4 5 6]
[7 8 9]]
Here, my_matrix is a 2D NumPy array with 3 rows and 3 columns. Each row is itself a one-dimensional array, and all rows are stacked together to form the two-dimensional structure. The shape of this matrix can be checked using:
print(my_matrix.shape)(3, 3)
This means the array has 3 rows and 3 columns.
In mathematics, such a two-dimensional array is called a matrix. A matrix is a rectangular arrangement of numbers, symbols, or expressions in rows and columns. It is often written as:
Each element of a matrix is identified by two indices — one for the row and one for the column.
For instance, the element in the second row and third column of the matrix $ A $ is:
In practical terms, a matrix might represent the word counts of several literary works, with each row standing for a text and each column representing a specific word. In another case, it could store the average temperatures across cities, where rows represent different countries and columns represent months.
Matrices allow us to perform mathematical operations such as scaling, transforming, and comparing data, which later become essential in tasks like measuring similarity between texts or analyzing historical trends numerically.
Creating Arrays with NumPy Functions
NumPy provides several convenient functions to create arrays quickly. Instead of typing long lists of numbers by hand, you can use these built-in methods to generate arrays with specific patterns or default values. This is especially useful when setting up simulations, preparing test data, or initializing analytical models.
Arrays from Ranges with np.arange()
The np.arange() function creates a sequence of numbers with regular spacing between them. Its three main arguments are:
- start – the first value in the sequence (included)
- stop – the end value (excluded)
- step – the difference between consecutive values
Let’s see it in action:
arr = np.arange(0, 10, 2)
print(arr)[0 2 4 6 8]
Here, NumPy starts at 0, adds 2 each time, and stops before reaching 10. The result is an evenly spaced sequence of numbers — something we often need in data visualization for defining axis ranges, or in modeling time intervals, such as years or decades.
Default Arrays with np.zeros() and np.ones()
When beginning a data analysis project, we sometimes need empty arrays to fill later with real data. NumPy provides two simple functions for this: np.zeros() and np.ones().
Each function takes a shape tuple, which defines the number of rows and columns.
zeros_2d = np.zeros((2, 3))
ones_2d = np.ones((3, 2))
print(zeros_2d, "\n\n", ones_2d)[[0. 0. 0.]
[0. 0. 0.]]
[[1. 1.]
[1. 1.]
[1. 1.]]
The first array contains only zeros, and the second only ones. These functions are helpful when setting up placeholders, initializing image data (where zeros might represent blank pixels), or defining model parameters before training a machine learning algorithm.
Evenly Spaced Values with np.linspace()
The np.linspace() function is used when you know how many values you want between two limits, rather than the step size. It creates evenly spaced numbers across an interval — including both endpoints.
arr = np.linspace(0, 10, 5)
print(arr)[ 0. 2.5 5. 7.5 10. ]
Here, NumPy has created five numbers evenly spaced between 0 and 10. This is particularly useful for creating smooth curves in visualizations or for dividing data into equal intervals, such as age groups or time segments.
Identity Matrices with np.eye()
The np.eye() function creates an identity matrix, a special kind of square matrix that has ones on its diagonal and zeros elsewhere.
In linear algebra, the identity matrix behaves like the number 1: multiplying any matrix by the identity matrix leaves it unchanged.
identity = np.eye(3)
print(identity)[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
Identity matrices are especially important in solving equations and performing transformations, as we’ll see later when we discuss matrix operations.
Data Types and Vectorized Computation
Every NumPy array stores elements of the same data type, also known as its dtype (short for data type). This could be an integer (int32, int64), a floating-point number (float32, float64), or even a string. To check an array’s data type, we can use the .dtype attribute.
arr = np.array([1, 2, 3])
print(arr.dtype)int64
The suffix 64 means that each integer occupies 64 bits. A signed int64 can represent integers from −263 to 263−1 exactly; fixed-width arithmetic can overflow outside that range. Floating-point precision is a separate property of floating-point dtypes. Because every element in an array shares the same type, NumPy can perform fast, vectorized computations — applying operations to all elements at once without writing loops.
Let’s look at an example:
arr = np.array([1, 2, 3, 4])
print(arr * 2)
print(arr + 10)
print(arr ** 2)[2 4 6 8]
[11 12 13 14]
[ 1 4 9 16]
Here, we multiplied, added, and squared the entire array in a single line each time. This behavior is called broadcasting, and it allows operations to “spread” automatically across all elements. For data analysis, this means you can transform entire datasets or apply mathematical formulas efficiently — for instance, converting all temperatures from Celsius to Fahrenheit at once.