☰

NumPy in Python

NumPy Tutorial in Python: Arrays, Functions and Examples

Try adding two lists of numbers in plain Python, and you will see the problem at once. The plus sign joins the lists instead of adding the numbers. To add them one by one, you must write a loop. NumPy removes that loop. You write a + b, and every pair of numbers is added, in a single line.

NumPy is the Python library for fast number work. It gives you a data type called the array, a grid of numbers that holds one type of value and does maths on all values together. Almost every data library in Python, such as pandas, SciPy, scikit learn and Matplotlib, is built on top of it. If you want to do data analysis or machine learning in Python, you will use NumPy sooner or later.

This tutorial starts with installation and takes you through arrays, shape, slicing, linspace, sums, standard deviation, stacking and broadcasting. Every example was run, and the output you see is the real output. We also show what goes wrong in the most common mistakes, with the exact error.

What is NumPy in Python?

NumPy stands for Numerical Python. It is a free, open source library for working with arrays of numbers. Its main object is the ndarray, a table of values that all have the same type, and that is indexed by whole numbers. It adds fast maths functions, tools for linear algebra, random numbers and Fourier transforms, and a way to join Python with code written in C, C plus plus and Fortran.

The simple way to think about it: a Python list holds anything, and an array holds one kind of thing, and because of that, NumPy can do maths on it very quickly.

Why Use NumPy Instead of a List?

Arrays take less memory, are fast and are convenient. Here is a test with one million whole numbers.

Python list compared with NumPy array
Python list NumPy array
Memory for 1,000,000 integers About 36 MB 8 MB
Maths on every item Needs a loop One line, no loop
Types inside Any mix One type
Speed for doubling every item Slower Faster

The memory figures came from a test I ran. The list figure counts the list and the number objects inside it, and it changes slightly between Python versions. In my run, doubling every item was more than 5 times faster with the array. The exact ratio depends on your computer, so test it on yours.

Features of NumPy

  • A powerful N dimensional array object. It can have one axis, two axes, or many more.
  • Broadcasting. NumPy can combine arrays of different shapes, such as adding one number to every item. We show an example below.
  • Fast maths functions. Sum, mean, standard deviation, square root and hundreds more work on whole arrays.
  • Tools for linear algebra, Fourier transforms and random numbers.
  • Tools to join Python with C, C plus plus and Fortran code.
  • The base of the data stack. pandas, SciPy, scikit learn and Matplotlib all use NumPy arrays.

How to Install NumPy?

The same one command works on Windows, Mac and Linux. Open a terminal, or Command Prompt on Windows, and run:

terminal
pip install numpy

If pip is not found, use python3 or py before it:

terminal
python -m pip install numpy

Now check that it worked, and see which version you have:

terminal
python -c "import numpy; print(numpy.__version__)"
output
2.5.3

Your number may be different. The NumPy 2.5.0 release notes list Python 3.12 to 3.14 as supported versions, and Python 3.11 is dropped. If you are on an older Python, pip may install an older NumPy, which is fine for everything in this tutorial except the descending sort at the end.

Installing NumPy on Mac

Open the Terminal and run pip install numpy, or python3 -m pip install numpy if the first command is not found.

Installing NumPy on Windows

The simplest way is the same command in Command Prompt. If you use PyCharm, you can also do it inside the editor. Open File, then Settings, then your project, then Python Interpreter. Click the plus button, search for numpy and click Install Package. The exact menu names differ a little between PyCharm versions, so check them against your version. Then add the line below at the top of your file and you are ready.

python
import numpy as np

Almost everybody writes np as the short name. Use np.

Properties of a NumPy Array

A NumPy array holds items of one type, and each item is found by its position, counted from zero. The directions of an array are called axes. A list of numbers has one axis. A table with rows and columns has two. Here is an example, a two row, three column table:

example
[[11, 22, 33],
 [44, 55, 66]]

This array has two axes. NumPy calls this ndim, the number of dimensions. Some older tutorials call it the rank, but rank in linear algebra means something different, so in NumPy it is safer to say ndim.

Your First NumPy Array

python
import numpy as np

a = np.array([2, 3, 4])
print(a)
output
[2 3 4]

Notice that the output has no commas. That is how NumPy prints an array, and it is a quick way to tell an array from a list.

Types of Arrays in NumPy

Single Dimension Arrays

A single dimension array has one axis, so it is a plain row of values.

python
import numpy as np

one = np.array([1, 8, 6])
print(one)
output
[1 8 6]

Multi Dimension Arrays

A multi dimension array has two or more axes. You build it with one list that contains the rows, so there are brackets around all the rows.

python
import numpy as np

two = np.array([[1, 2, 3], [4, 5, 6]])
print(two)
output
[[1 2 3]
 [4 5 6]]

A common mistake is to pass each row separately. It fails like this:

python
np.array([1, 2, 4], [2, 5, 7])
output
TypeError: Field elements must be 2- or 3-tuples, got '2'

The message is confusing, because the second list was read as a type description. The fix is simple. Put one more pair of brackets around the rows.

What Happens When Types are Mixed?

An array has one type, so NumPy converts the values to fit.

python
print(np.array([1, 2.5, 3]).dtype)
print(np.array([1, "a"]).dtype)
output
float64
<U21

Whole numbers and a decimal become decimals. Numbers and text all become text, shown here as U21, which means text strings. This surprises beginners, so check the type if a calculation does not behave.

Common NumPy Array Attributes and Functions

The names ndim, itemsize and dtype are attributes, and the rest are functions. Operators are signs such as plus and minus, and we cover those in a later section.

ndim, shape, size, itemsize and dtype

python
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.ndim)
print(a.shape)
print(a.size)
print(a.itemsize)
print(a.dtype)
output
2
(2, 3)
6
8
int64
Array attributes
Attribute What it tells you
ndim The number of axes, which is 2 here
shape The size along each axis, which is 2 rows and 3 columns
size The total number of items, which is 6
itemsize The bytes used by each item, which is 8 here
dtype The data type of the items, which is int64 here

The output of itemsize and dtype depends on your system. On most 64 bit computers, whole numbers are int64, but on some Windows setups with older NumPy versions you may see int32 and 4. The attribute shape is the one you will use the most.

reshape

Reshape changes the rows and columns without changing the data. The total number of items must stay the same.

python
print(a.reshape(3, 2))
output
[[1 2]
 [3 4]
 [5 6]]

If you ask for a shape that does not fit, such as 4 by 2 for six items, NumPy raises a ValueError. Use minus 1 for one side, such as reshape(3, -1), and NumPy works out the missing number.

Slicing

Slicing picks out parts of an array. Write the row first, then the column, separated by a comma. A colon means all of the rows or columns.

python
s = np.array([[1, 2, 3], [4, 5, 6], [11, 12, 13]])
print(s[0, 2])
print(s[0:, 2])
print(s[0:2, 1])
output
3
[ 3  6 13]
[2 5]
What each slice does
Code What it does
s[0, 2] Row 0, column 2. The answer is 3
s[0:, 2] All rows from row 0 onward, column 2. The answer is 3, 6 and 13
s[0:2, 1] Rows 0 and 1 only, column 1. The answer is 2 and 5

Remember that the end number in a slice is not included. So 0:2 means rows 0 and 1, and not row 2.

linspace

The function linspace gives evenly spaced numbers between two points. Be careful with the spelling. A common typo, linespace, raises an AttributeError.

python
print(np.linspace(1, 3, 10))
output
[1.         1.22222222 1.44444444 1.66666667 1.88888889 2.11111111
 2.33333333 2.55555556 2.77777778 3.        ]

The three numbers are the start, the end and how many values you want. Both ends are included. A shorter case, with 5 values, is easier to read:

python
print(np.linspace(1, 3, 5))
output
[1.  1.5 2.  2.5 3. ]

Linspace is very handy for the x values of a chart. We use it in our Matplotlib tutorial.

max, min, sum, sqrt and std

These five do most of the everyday work. Call them with the np prefix where needed, for example np.sqrt. Without the prefix Python raises a NameError.

python
print(a.max())
print(a.min())
print(a.sum())
print(np.round(np.sqrt(a), 2))
print(round(float(a.std()), 4))
output
6
1
21
[[1.   1.41 1.73]
 [2.   2.24 2.45]]
1.7078
What the functions do
Function What it does
max The largest value in the array
min The smallest value
sum The total of all values
sqrt The square root of every value, which gives a new array
std The standard deviation, a measure of how spread out the values are

Totals by Row or by Column with axis

A single total is not always what you need. The axis argument says in which direction to work. Axis 0 goes down the columns, and axis 1 goes across the rows.

python
print(a.sum(axis=0))
print(a.sum(axis=1))
output
[5 7 9]
[ 6 15]

The first line gives the total of each column. The second gives the total of each row. This one idea saves a lot of loops in real work.

A Trap: Python max Versus NumPy max

Plain Python max on a two row array fails:

python
max(a)
output
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Python tries to compare whole rows, and cannot decide which row is bigger. Use a.max() or np.max(a) instead. The plain Python sum happens to work, but it adds row by row and gives [5 7 9], not 21, so use a.sum() when you want the single total.

Arithmetic on Arrays

The plus, minus, times and divide signs work on every pair of items at the same position. The two arrays need the same shape.

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

print(a + b)
print(a - b)
print(a * b)
print(np.round(a / b, 2))
output
[[ 6  4  9]
 [12  9 12]]
[[-4  0 -3]
 [-4  1  0]]
[[ 5  4 18]
 [32 20 36]]
[[0.2  1.   0.5 ]
 [0.5  1.25 1.  ]]

Note that a * b multiplies item by item. It is not the same as matrix multiplication, which uses the at sign, as in a @ b.

Broadcasting: Maths With a Single Number

Broadcasting is what lets NumPy combine arrays of different shapes. The simplest case is one number and an array. Here, 5 bonus marks are added to every student, and each mark is raised by 10 percent.

python
marks = np.array([72, 88, 91, 65])
print(marks + 5)
print(marks * 1.1)
output
[77 93 96 70]
[ 79.2  96.8 100.1  71.5]

Filtering With a Condition

You can use a condition inside the brackets to keep only some values. This is very useful in data work.

python
print(marks[marks >= 70])
print((marks >= 70).sum())
output
[72 88 91]
3

The first line gives the marks that are 70 or more. The second counts how many there are, because True counts as 1.

Vertical and Horizontal Stacking

Stacking joins arrays. Use vstack to put one below the other, and hstack to put them side by side.

python
print(np.vstack((a, b)))
print(np.hstack((a, b)))
output
[[1 2 3]
 [4 5 6]
 [5 2 6]
 [8 4 6]]
[[1 2 3 5 2 6]
 [4 5 6 8 4 6]]

Note the double brackets. The function takes one group of arrays, so the arrays go inside their own brackets. For vstack the arrays need the same number of columns, and for hstack the same number of rows.

Ravel: Flatten an Array

Ravel turns any array into a flat, one dimensional array. The result has one axis only, and its shape is (6,), so it is not a column.

python
print(a.ravel())
print(a.ravel().shape)
output
[1 2 3 4 5 6]
(6,)

Sorting in Descending Order (New in NumPy 2.5)

Before NumPy 2.5, you had to sort and then reverse. The 2.5.0 release notes say np.sort and np.argsort now accept descending=True. The notes also say that NaN values go to the end in both directions, and that descending sorts may be slower, because the fast SIMD sorting is not used for them.

python
print(np.sort(marks, descending=True))
output
[91 88 72 65]

If you are on an older NumPy, this line raises a TypeError. Use np.sort(marks)[::-1] there instead.

Common NumPy Errors and How to Fix Them

NumPy errors and fixes
Error Usual cause Fix
AttributeError: no attribute linespace A spelling mistake in linspace Use np.linspace
NameError: name sqrt is not defined The np prefix is missing Use np.sqrt
NameError: name x is not defined Using a variable that was never created Use the name you created, such as a
TypeError: Field elements must be 2 or 3 tuples Rows passed as separate arguments Wrap all rows in one more pair of brackets
ValueError: truth value of an array is ambiguous Plain Python max or min on a 2D array Use a.max() or np.max(a)
ValueError: cannot reshape array The new shape has a different item count Make rows times columns equal to size
ModuleNotFoundError: No module named numpy NumPy is not installed in this Python Run python -m pip install numpy

What is New in NumPy 2.5?

The 2.5.0 release notes list these main points. You do not need them to learn the basics, but they show where the library is going.

  • Descending sort with descending=True for np.sort and np.argsort.
  • Pattern matching. An ndarray works with match and case statements.
  • New polynomial functions for several variables, such as polyvalnd.
  • Cleaner base. Distutils is removed, and many old deprecations have now ended.
  • Better typing and better support for free threaded Python.

If you are upgrading from NumPy 1.x, read the release notes before you update, because some old functions have been removed over the 2.x releases.

Practice Exercises

  1. Create a 3 by 4 array with the numbers 1 to 12 using np.arange(1, 13).reshape(3, 4). Print its shape and its sum.
  2. Print the total of each column and each row using the axis argument.
  3. Slice out the last two columns of the array.
  4. Create the marks 72, 88, 91 and 65 as an array and add 5 bonus marks to anyone who scored below 70.
  5. Stack two arrays, first one below the other, and then side by side. Then flatten the result with ravel.

Complete Script to Run Yourself

Here is the full script that was used to test the examples on this page. It ran on NumPy 2.5.3. The speed test prints only True or False, because the exact times change from one computer to another.

python
import sys
import numpy as np

print(np.__version__)

# 1. Create arrays
one = np.array([1, 8, 6])
two = np.array([[1, 2, 3], [4, 5, 6]])
print(one)
print(two)

# 2. Attributes
print(two.ndim, two.shape, two.size, two.itemsize, two.dtype)

# 3. A wrong multi dimension line
try:
    np.array([1, 2, 4], [2, 5, 7])
except TypeError as e:
    print("TypeError:", e)

# 4. Reshape
print(two.reshape(3, 2))

# 5. Slicing
s = np.array([[1, 2, 3], [4, 5, 6], [11, 12, 13]])
print(s[0, 2])
print(s[0:, 2])
print(s[0:2, 1])

# 6. linspace
print(np.linspace(1, 3, 10))
print(np.round(np.linspace(1, 3, 5), 2))

# 7. Functions
print(two.max(), two.min(), two.sum(), np.round(np.sqrt(two), 2), round(float(two.std()), 4))
print(two.sum(axis=0), two.sum(axis=1))
print(sum(two))
try:
    max(two)
except ValueError as e:
    print("ValueError:", e)

# 8. Arithmetic
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[5, 2, 6], [8, 4, 6]])
print(a + b)
print(a - b)
print(np.round(a / b, 2))
print(a * b)

# 9. Stacking
print(np.vstack((a, b)))
print(np.hstack((a, b)))

# 10. Ravel
print(a.ravel(), a.ravel().shape)

# 11. Broadcasting
marks = np.array([72, 88, 91, 65])
print(marks + 5)
print(marks * 1.1)

# 12. Boolean filter
print(marks[marks >= 70], (marks >= 70).sum())

# 13. Memory
lst = list(range(1_000_000))
arr = np.arange(1_000_000)
print(arr.nbytes)
print(sys.getsizeof(lst) + sum(sys.getsizeof(i) for i in lst))

# 14. Speed (ratio only, will vary)
import timeit
tl = timeit.timeit(lambda: [x * 2 for x in lst], number=5)
ta = timeit.timeit(lambda: arr * 2, number=5)
print(tl / ta > 5)

# 15. Descending sort (NumPy 2.5)
print(np.sort(marks, descending=True))

# 16. Dtype mixing
print(np.array([1, 2.5, 3]).dtype, np.array([1, "a"]).dtype)

NumPy is small to learn and large in its effect. If you can create an array, check its shape, slice it, and do maths on it without a loop, you already have the skill that pandas, scikit learn and Matplotlib expect. Type the examples yourself, break them on purpose, and read the error messages, because that is where the learning happens. A good next step is to use the arrays you made here to draw a chart in Matplotlib, or load them into a pandas table.

Popular Tags:

Numpy Tutorial in Python Python NumPy Tutorials