# Moving from MATLAB matrices to NumPy arrays

### - A Matrix Cheatsheet

-- written by Sebastian Raschka on January 22, 2014

Over time Python became my favorite programming language for the quick automation of tasks, such as manipulating and analyzing data. Also, I grew fond of the great matplotlib plotting library for Python.
MATLAB/Octave was usually my tool of choice when my tasks involved matrices and linear algebra. However, since I feel more comfortable with Python in general, I recently took a second look at Python’s NumPy module to integrate matrix operations more easily into larger programs/scripts.

Last Updated: 04/03/2014

Eventually, I collected some of the basic and most common matrix functions of MATLAB/Octave and compiled a list to compare them to their NumPy array equivalents; something I wanted to share in hope that it might be useful to other MATLAB/Octave users who are thinking about a migration to Python NumPy to perform matrix operations.

Note: in order to use `"numpy"` as `"np"` as shown in the table, you need to import NumPy like this:
`import numpy as np`

MATLAB/Octave NumPy
Creating Matrices
(here: 3x3 matrix)
>> A = [1 2 3; 4 5 6; 7 8 9]
A =
1   2   3
4   5   6
7   8   9
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> A
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
Getting the dimension
of a matrix
(here: 2D, rows x cols)
>> A = [1 2 3; 4 5 6]
A =
1   2   3
4   5   6
>> size(A)
ans =
2   3
>> A = np.array([ [1,2,3], [4,5,6] ])
>> A
array([[1, 2, 3],
[4, 5, 6]])
>> A.shape
(2, 3)
Selecting rows  >> A = [1 2 3; 4 5 6; 7 8 9]

% first row
>> A(1,:)
ans =
1   2   3

% first 2 rows
>> A(1:2,:)
ans =
1   2   3
4   5   6
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])

# first row
>> A[0,:]
array([1, 2, 3])

# first 2 rows
>> A[0:2,:]
array([[1, 2, 3], [4, 5, 6]])
Selecting columns >> A = [1 2 3; 4 5 6; 7 8 9]

% first column
>> A(:,1)
ans =
1
4
7

% first 2 columns
>> A(:,1:2)
ans =
1   2
4   5
7   8
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])

# first column (as row vector)
>> A[:,0]
array([1, 4, 7])

# first column (as column vector)
>> A[:,[0]]
array([[1],
[4],
[7]])

# first 2 columns
>> A[:,0:2]
array([[1, 2],
[4, 5],
[7, 8]])
Extracting rows and
columns by criteria
(here: get rows
that have value 9
in column 3)
>> A = [1 2 3; 4 5 9; 7 8 9]
A =
1   2   3
4   5   9
7   8   9
>> A(A(:,3) == 9,:)
ans =
4   5   9
7   8   9
>> A = np.array([ [1,2,3], [4,5,9], [7,8,9]])
>> A
array([[1, 2, 3],
[4, 5, 9],
[7, 8, 9]])
>>> A[A[:,2] == 9]
array([[4, 5, 9],
[7, 8, 9]])
Accessing elements
(here: first element)
>> A = [1 2 3; 4 5 6; 7 8 9]
>> A(1,1)
ans =  1
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> A[0,0]
1
Creating an
1D column vector
>> a = [1; 2; 3]
a =
1
2
3
>> a = np.array([[1],[2],[3]])
>> a
array([[1],
[2],
[3]])
Creating an
1D row vector
>> b = [1 2 3]
b =
1   2   3
>> b = np.array([1,2,3])
>> b
array([1, 2, 3])
Converting
row to column vectors
>> b = [1 2 3]'
b =
1
2
3
>> b = np.array([1, 2, 3])
>> b = b[np.newaxis].T
# alternatively  b = b[:,np.newaxis]
>> b
array([[1],
[2],
[3]])
Reshaping Matrices
(here: 3x3 matrix to row vector)
>> A = [1 2 3; 4 5 6; 7 8 9]
A =
1   2   3
4   5   6
7   8   9
>> total_elements = numel(A)
>> B = reshape(A,1,total_elements)
% or reshape(A,1,9)
B =
1   4   7   2   5   8   3   6   9
>> A = np.array([[1,2,3],[4,5,6],[7,8,9]])
>> A
array([[1, 2, 3],
[4, 5, 9],
[7, 8, 9]])
>> total_elements = A.shape[0] * A.shape[1]
>> B = A.reshape(1, total_elements)
# or A.reshape(1,9)
# Alternative: A.shape = (1,9)
# to change the array in place
>> B
array([[1, 2, 3, 4, 5, 6, 7, 8, 9]])
Concatenating matrices >> A = [1 2 3; 4 5 6]
>> B = [7 8 9; 10 11 12]
>> C = [A; B]
1    2    3
4    5    6
7    8    9
10   11   12
>> A = np.array([[1, 2, 3], [4, 5, 6]])
>> B = np.array([[7, 8, 9],[10,11,12]])
>> C = np.concatenate((A, B), axis=0)
>> C
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])
Stacking
vectors and matrices
>> a = [1 2 3]
>> b = [4 5 6]

>> c = [a' b']
c =
1   4
2   5
3   6

>> c = [a; b]
c =
1   2   3
4   5   6
>> a = np.array([1,2,3])
>> b = np.array([4,5,6])

>> np.c_[a,b]
array([[1, 4],
[2, 5],
[3, 6]])

>> np.r_[a,b]
array([[1, 2, 3],
[4, 5, 6]])
Creating a
random m x n matrix
>> rand(3,2)
ans =
0.21977   0.10220
0.38959   0.69911
0.15624   0.65637
>> np.random.rand(3,2)
array([[ 0.29347865,  0.17920462],
[ 0.51615758,  0.64593471],
[ 0.01067605,  0.09692771]])
Creating a
zero m x n matrix
>> zeros(3,2)
ans =
0   0
0   0
0   0
>> np.zeros((3,2))
array([[ 0.,  0.],
[ 0.,  0.],
[ 0.,  0.]])
Creating an
m x n matrix of ones
>> ones(3,2)
ans =
1   1
1   1
1   1
>> np.ones([3,2])
array([[ 1.,  1.],
[ 1.,  1.],
[ 1.,  1.]])
Creating an
identity matrix
>> eye(3)
ans =
Diagonal Matrix
1   0   0
0   1   0
0   0   1
>> np.eye(3)
array([[ 1.,  0.,  0.],
[ 0.,  1.,  0.],
[ 0.,  0.,  1.]])
Creating a
diagonal matrix
>> a = [1 2 3]
>> diag(a)
ans =
Diagonal Matrix
1   0   0
0   2   0
0   0   3
>> a = np.array([1,2,3])
>> np.diag(a)
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
Matrix-scalar
operations
>> A = [1 2 3; 4 5 6; 7 8 9]
>> A * 2
ans =
2    4    6
8   10   12
14   16   18
>> A + 2
>> A - 2
>> A / 2
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> A * 2
array([[ 2,  4,  6],
[ 8, 10, 12],
[14, 16, 18]])
>> A + 2
>> A - 2
>> A / 2
Matrix-matrix
multiplication
>> A = [1 2 3; 4 5 6; 7 8 9]
>> A * A
ans =
30    36    42
66    81    96
102   126   150
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> np.dot(A,A) # or A.dot(A)
array([[ 30,  36,  42],
[ 66,  81,  96],
[102, 126, 150]])
Matrix-vector
multiplication
>> A = [1 2 3; 4 5 6; 7 8 9]
>> B = [ 1; 2; 3 ]
>> A * B
ans =
14
32
50
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> B = np.array([ [1], [2], [3] ])
>> np.dot(A,B) # or A.dot(B)

array([[14], [32], [50]])
Element-wise
matrix-matrix
operations
>> A = [1 2 3; 4 5 6; 7 8 9]
>> A .* A
ans =
1    4    9
16   25   36
49   64   81

>> A .+ A
>> A .- A
>> A ./ A
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> A * A
array([[ 1,  4,  9],
[16, 25, 36],
[49, 64, 81]])

>> A + A
>> A - A
>> A / A
Matrix elements
to power n
>> A = [1 2 3; 4 5 6; 7 8 9]
>> A.^2
ans =
1    4    9
16   25   36
49   64   81
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> np.power(A,2)
array([[ 1,  4,  9],
[16, 25, 36],
[49, 64, 81]])
Matrix to power n
(matrix-matrix
multiplication
with itself)
>> A = [1 2 3; 4 5 6; 7 8 9]
>> A ^ 2
ans =
30    36    42
66    81    96
102   126   150
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>>> np.linalg.matrix_power(A,2)
array([[ 30,  36,  42],
[ 66,  81,  96],
[102, 126, 150]])
Matrix transpose >> A = [1 2 3; 4 5 6; 7 8 9]
>> A'
ans =
1   4   7
2   5   8
3   6   9
>> A = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
>> A.T
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
Determinant of a matrix:
A -> |A|
>> A = [6 1 1; 4 -2 5; 2 8 7]
A =
6   1   1
4  -2   5
2   8   7
>> det(A)
ans = -306
>> A = np.array([[6,1,1],[4,-2,5],[2,8,7]])
>> A
array([[ 6,  1,  1],
[ 4, -2,  5],
[ 2,  8,  7]])
>> np.linalg.det(A)
-306.0
Inverse of a matrix >> A = [4 7; 2 6]
A =
4   7
2   6
>> I = [1 0; 0 1]
I =
1   0
0   1
>> A_inv = inv(A)
A_inv =
0.60000  -0.70000
-0.20000   0.40000
>> A = np.array([[4, 7], [2, 6]])
>> A
array([[4, 7],
[2, 6]])
>> I = np.array([[1, 0], [0, 1]])
>> I
array([[1, 0],
[0, 1]])
>> A_inverse = np.linalg.inv(A)
>> A_inverse
array([[ 0.6, -0.7],
[-0.2, 0.4]])

# A * A^-1 should yield the Identity matrix
assert(np.dot(A, A_inverse).all() == I.all())
Calculating a
covariance matrix
of 3 random variables
(here: covariances of
the means
of x1, x2, and x3)
>> x1 = [4.0000 4.2000 3.9000 4.3000 4.1000]’
>> x2 = [2.0000 2.1000 2.0000 2.1000 2.2000]'
>> x3 = [0.60000 0.59000 0.58000 0.62000 0.63000]’

>> cov( [x1,x2,x3] )
ans =
2.5000e-02   7.5000e-03   1.7500e-03
7.5000e-03   7.0000e-03   1.3500e-03
1.7500e-03   1.3500e-03   4.3000e-04
>> x1 = np.array([ 4, 4.2, 3.9, 4.3, 4.1])
>> x2 = np.array([ 2, 2.1, 2, 2.1, 2.2])
>> x3 = np.array([ 0.6, 0.59, 0.58, 0.62, 0.63])
>> np.cov([x1, x2, x3])
array([[ 0.025  ,  0.0075 ,  0.00175],
[ 0.0075 ,  0.007  ,  0.00135],
[ 0.00175,  0.00135,  0.00043]])
Calculating
eigenvectors and
eigenvalues
>> A = [3 1; 1 3]
A =
3   1
1   3

>> [eig_vec,eig_val] = eig(A)
eig_vec =
-0.70711   0.70711
0.70711   0.70711
eig_val =
Diagonal Matrix
2   0
0   4
>> A = np.array([[3, 1], [1, 3]])
>> A
array([[3, 1],
[1, 3]])

>> eig_val, eig_vec = np.linalg.eig(A)
>> eig_val
array([ 4.,  2.])
>> eig_vec
array([[ 0.70710678, -0.70710678],
[ 0.70710678,  0.70710678]])
Generating a Gaussion dataset:
creating random vectors from the multivariate normal
distribution given mean and covariance matrix(here: 5 random vectors with
mean 0, covariance = 0, variance = 2)
% requires statistics toolbox package
% how to install and load it in Octave:

% http://octave.sourceforge.net/packages.php
% pkg install
%     ~/Desktop/io-2.0.2.tar.gz
% pkg install
%     ~/Desktop/statistics-1.2.3.tar.gz

>> mean = [0 0]
>> cov = [2 0; 0 2]
cov =
2   0
0   2
>> mvnrnd(mean,cov,5)
2.480150  -0.559906
-2.933047   0.560212
0.098206   3.055316
-0.985215  -0.990936
1.122528   0.686977

>> mean = np.array([0,0])
>> cov = np.array([[2,0],[0,2]])
>> np.random.multivariate_normal(mean, cov, 5)

array([[ 1.55432624, -1.17972629],
[-2.01185294, 1.96081908],
[-2.11810813, 1.45784216],
[-2.93207591, -0.07369322],
[-1.37031244, -1.18408792]])

## NumPy matrix vs. NumPy array

While NumPy arrays are the basic types in NumPy, there is also a matrix type with very similar behavior. For most people who are familiar with MATLAB/Octave, NumPy matrix syntax might feel a little bit more natural. One of the differences is, for example, that the "`*`" operator is used for matrix-matrix multiplication of NumPy matrices, where the same operator performs element-wise multiplication on NumPy arrays. Vice versa, the "`.dot()`" method is used for element-wise multiplication in NumPy matrices, where "`*`" is used for the same operation on NumPy matrices. Most people recommend the use of the NumPy array type over NumPy matrices, since arrays are what most of the NumPy functions return.