How do I create and manipulate matrices in Python?

Although there are several ways to do this, one of the easiest is to use the NumPy library. NumPy has many built-in commands to create arrays. For example:

  • np.array(List) creates a NumPy array from a Python list. The size and shape of the array depend on the list entries.
  • np.eye(N) creates an NxN identity matrix
  • np.random.random((M,N)) creates an MxN matrix of random numbers between 0 and 1

NumPy also includes many built-in commands to manipulate arrays in matrix-like ways. For example:

  • A+B gives the element-wise sum of two arrays A and B
  • A*B gives the element-wise product of two arrays A and B
  • A@B gives the matrix product of two arrays A and B
  • A.T or np.transpose(A) gives the transpose of the array A

There are many, many things you can do with NumPy arrays! These FAQs will give just a few examples that come up often in our work.

How do I make NumPy matrix printouts easier to read?

Two commands are helpful:

  • np.set_printoptions(suppress=True) will supress the use of scientific notation
  • np.set_printoptions(precision=N) will control the number N of decimals to print
In [12]:
import numpy as np

A = np.exp(10*np.random.random((4,4)))

np.set_printoptions(suppress=False)
print('Using scientific notation:')
print(A)
print()

print('Suppressing scientific notation:')
np.set_printoptions(suppress=True)
print(A)
print()

print('Lowering the print precision:')
np.set_printoptions(precision=2)
print(A)
print()
Using scientific notation:
[[  2.21e+02   4.93e+02   5.36e+00   2.30e+00]
 [  4.27e+00   1.22e+02   2.71e+03   1.79e+00]
 [  8.65e+01   9.00e+02   2.57e+03   7.43e+02]
 [  1.42e+01   3.84e+01   4.47e+00   6.59e+03]]

Suppressing scientific notation:
[[  220.95   493.18     5.36     2.3 ]
 [    4.27   122.    2705.98     1.79]
 [   86.47   900.48  2569.42   742.66]
 [   14.18    38.41     4.47  6588.18]]

Lowering the print precision:
[[  220.95   493.18     5.36     2.3 ]
 [    4.27   122.    2705.98     1.79]
 [   86.47   900.48  2569.42   742.66]
 [   14.18    38.41     4.47  6588.18]]

How does NumPy array indexing work?

Complete documentation on NumPy indexing can be found at the NumPy project page: https://numpy.org/doc/stable/user/basics.indexing.html.

Here we only give a few examples that we find useful. The examples here are for 1D arrays, but indexing works similarly for 2D (or 3D or 4D...) arrays, with commas separating the different dimensions. E.g. A[0,0] corresponds to the zeroth row and zeroth column of the array A, A[0,1] corresponds to the zeroth row and 1th column, etc.

Note that array indexing in NumPy starts at 0, not at 1!

In [4]:
import numpy as np 

# A contains numbers 0 through 9
A = np.arange(0, 10)
print('A:')
print(A)
print()

# This is a vector of length 10, i.e., shape is (10,).
# Note that (to NumPy) this is different from a matrix 
# of dimension (10,1), i.e., a 10x1 matrix. 
print('np.shape(A):')
print(np.shape(A))
print()

print('Backwards array:')
print(A[::-1])
print()

print('First element:')
print(A[0])
print()

print('Last element')
print(A[-1])
print()

print('Penultimate element:')
print(A[-2])
print()

print('Even elements')
print(A[0::2])
print()

print('Odd elements')
print(A[1::2])
print()

print('Every thid element')
print(A[0::3])
print()

print('First 4 elements:')
print(A[0:4])
print()

print('First 2 even elements:')
print(A[0:4:2])
print()

print('Odd elements backwards:')
print(A[::-2])
print()
A:
[0 1 2 3 4 5 6 7 8 9]

np.shape(A):
(10,)

Backwards array:
[9 8 7 6 5 4 3 2 1 0]

First element:
0

Last element
9

Penultimate element:
8

Even elements
[0 2 4 6 8]

Odd elements
[1 3 5 7 9]

Every thid element
[0 3 6 9]

First 4 elements:
[0 1 2 3]

First 2 even elements:
[0 2]

Odd elements backwards:
[9 7 5 3 1]

How do I calculate a matrix product in Python?

Using the NumPy library, you can apply the @ symbol:

In [5]:
import numpy as np 

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

print('A:')
print(A)
print()

print('B:')
print(B)
print()

print('A*B: ')
print(A*B)
print()

print('A@B: ')
print(A@B)
print()

print('B@A: ')
print(B@A)
print()
A:
[[1 2]
 [3 4]]

B:
[[5 6]
 [7 8]]

A*B: 
[[ 5 12]
 [21 32]]

A@B: 
[[19 22]
 [43 50]]

B@A: 
[[23 34]
 [31 46]]

How do I calculate a matrix inverse in Python?

Use the np.linalg.inv() command:

In [6]:
# Original matrix
A = np.array([[1, 2], [3,4]])

# Inverse
Ainv = np.linalg.inv(A)

print('Ainv:')
print(Ainv)
print()

# The product of the two should be (very nearly) the identity matrix
print('A@Ainv:')
print(A@Ainv)
Ainv:
[[-2.   1. ]
 [ 1.5 -0.5]]

A@Ainv:
[[ 1.  0.]
 [ 0.  1.]]

How do I calculate eigenvalues and eigenvectors in Python?

Use the np.linalg.eig or np.linalg.eigh commands:

In [7]:
A = np.array([[-20, 50],[50, 10]])

evals, evecs = np.linalg.eigh(A)

print('A:')
print(A)
print()

print('Eigenvalues:')
print(evals)
print()

print('Eigenvectors:')
print(evecs)
print()

# evecs.T @ A @ evecs should be a diagonal matrix
# whose entries are the eigevectors corresponding
# to each eigenvalue:
print('Diagonalization:')
print(np.transpose(evecs)@A@evecs)
A:
[[-20  50]
 [ 50  10]]

Eigenvalues:
[-57.2  47.2]

Eigenvectors:
[[-0.8 -0.6]
 [ 0.6 -0.8]]

Diagonalization:
[[-57.2   0. ]
 [  0.   47.2]]

How do I print NumPy arrays to a text file?

The easiest way to do this is probably using np.savetxt(). The delimiter flag can be used to indicate a customized string to separate the numeric data. (The default is a single white space.)

In [20]:
import numpy as np 

dat = np.random.random((10,5))
print(dat)
np.savetxt('default.txt', dat)
np.savetxt('tabs.txt', dat, delimiter='\t')
np.savetxt('commas.txt', dat, delimiter=',')
[[ 0.6   0.02  0.31  0.89  0.49]
 [ 0.88  0.01  0.14  0.06  0.47]
 [ 0.35  0.07  0.59  0.97  0.06]
 [ 0.17  0.51  0.87  0.4   0.62]
 [ 0.28  0.98  0.72  0.72  0.31]
 [ 0.32  0.1   0.31  0.7   0.04]
 [ 1.    0.6   0.95  0.19  0.64]
 [ 0.28  0.04  0.08  0.25  0.48]
 [ 0.31  0.77  0.22  0.67  0.55]
 [ 0.7   0.86  0.99  0.88  0.02]]

How do I control output precision with np.savetxt()?

Use the optional fmt flag. There are many options here, but as two most important examples:

  • To keep 5 decimal places, with scientific notation, set fmt='%.5e'.
  • To keep 5 decimal places, without scientific notation, set fmt='%.5f'. You can replace 5 here with however many decimal points you wish to preserve.
In [28]:
import numpy as np 

dat = np.random.random((10,5))

# One decimal point, no scientific notation:
np.savetxt('precision1.txt', dat, fmt='%.1f')

# Five decimal points, no scientific notation:
np.savetxt('precision5.txt', dat, fmt='%.5f')

# Five decimal points, with scientific notation:
np.savetxt('precision5sci.txt', dat, fmt='%.5e')

How do I load tab-delimited data from a text file into a NumPy array?

There are several ways to do this, but the easiest is probably np.loadtxt(). Note that the text file must contain only numeric data, with the same number of data points in each line of the file (so that it can be loaded into a rectangular array).

In [32]:
import numpy as np 

# Set print precision to 10 decimals
np.set_printoptions(precision=10)

dat = np.random.random((10,5))
print('Original data:')
print(dat)
print()

# Save the data with two different precisions:
np.savetxt('precision1.txt', dat, fmt='%.1f')
np.savetxt('precision5.txt', dat, fmt='%.5f')

dat1 = np.loadtxt('precision1.txt')
print('From 1-decimal precision file:')
print(dat1)
print()

# From 5-decimal precision file:
dat5 = np.loadtxt('precision5.txt')
print('From 5-decimal precision file:')
print(dat5)
print()
Original data:
[[ 0.9364172975  0.4736766478  0.3954997522  0.2295961172  0.5051098805]
 [ 0.095599225   0.7531380077  0.4123492077  0.8539660432  0.2580521103]
 [ 0.7192928198  0.4902830369  0.9877565876  0.2414540092  0.6751003157]
 [ 0.0967878487  0.8047707196  0.0339582619  0.5756287273  0.4723487975]
 [ 0.9758369182  0.840540963   0.3166136108  0.5956060309  0.5684113764]
 [ 0.7213089001  0.0400370272  0.1958339652  0.8556262046  0.8616145738]
 [ 0.0971277627  0.9474437754  0.4641328625  0.4234104172  0.4627724561]
 [ 0.1742203323  0.8376111942  0.1049220714  0.3396354636  0.6953630936]
 [ 0.8158853383  0.8313302568  0.0834473049  0.2550371527  0.1720891566]
 [ 0.9344406263  0.8608303234  0.1139978681  0.6795782679  0.5558488537]]

From 1-decimal precision file:
[[ 0.9  0.5  0.4  0.2  0.5]
 [ 0.1  0.8  0.4  0.9  0.3]
 [ 0.7  0.5  1.   0.2  0.7]
 [ 0.1  0.8  0.   0.6  0.5]
 [ 1.   0.8  0.3  0.6  0.6]
 [ 0.7  0.   0.2  0.9  0.9]
 [ 0.1  0.9  0.5  0.4  0.5]
 [ 0.2  0.8  0.1  0.3  0.7]
 [ 0.8  0.8  0.1  0.3  0.2]
 [ 0.9  0.9  0.1  0.7  0.6]]

From 5-decimal precision file:
[[ 0.93642  0.47368  0.3955   0.2296   0.50511]
 [ 0.0956   0.75314  0.41235  0.85397  0.25805]
 [ 0.71929  0.49028  0.98776  0.24145  0.6751 ]
 [ 0.09679  0.80477  0.03396  0.57563  0.47235]
 [ 0.97584  0.84054  0.31661  0.59561  0.56841]
 [ 0.72131  0.04004  0.19583  0.85563  0.86161]
 [ 0.09713  0.94744  0.46413  0.42341  0.46277]
 [ 0.17422  0.83761  0.10492  0.33964  0.69536]
 [ 0.81589  0.83133  0.08345  0.25504  0.17209]
 [ 0.93444  0.86083  0.114    0.67958  0.55585]]

How do I load comma-delimited data from a text file into a NumPy array?

The syntax is the same as for tab-delimited data, but you must add the flag delimiter=','.

In [34]:
import numpy as np 

dat = np.random.random((10,5))
np.savetxt('precision5.txt', dat, fmt='%.5f', delimiter=',')

# From 5-decimal precision file:
dat5 = np.loadtxt('precision5.txt', delimiter=',')
print('From 5-decimal precision file:')
print(dat5)
print()
From 5-decimal precision file:
[[ 0.13734  0.38584  0.62563  0.40165  0.07293]
 [ 0.78286  0.7793   0.84418  0.19475  0.28821]
 [ 0.56998  0.57984  0.0595   0.98685  0.34097]
 [ 0.02003  0.8407   0.09316  0.83485  0.32105]
 [ 0.9363   0.30436  0.62536  0.32022  0.97255]
 [ 0.3708   0.56985  0.83221  0.63474  0.14423]
 [ 0.96803  0.27683  0.80708  0.49152  0.22155]
 [ 0.15709  0.27297  0.73944  0.6462   0.54357]
 [ 0.55036  0.58456  0.65004  0.39913  0.87641]
 [ 0.55787  0.98461  0.47396  0.15595  0.10621]]

In [ ]: