Getting Things Done in Python

This notebook contains tips and tricks of working with vectors and matrices:

  • How to generate arrays of numbers
  • How to generate, matrices, row- and column-vectors
  • How to reotate vectors
  • And a first introduction into the often very valuable concept of "broadcasting"

author: Thomas Haslwanter, date: Feb-2017

Generating Data

Generating Evenly Spaced Vectors

In [1]:
# import standard packages
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import frange

# To make the display prettier
%precision 3
Out[1]:
'%.3f'
In [2]:
# Note that with "arange" the last value is NOT included!
x = np.arange(1,5,0.5)
x
Out[2]:
array([ 1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5])
In [3]:
# "linspace" produces a given number of linearly spaced numbers
y = np.linspace(0,1,11)
y
Out[3]:
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
In [4]:
# "frange" includes the last value
z = frange(1,3)
z
Out[4]:
array([ 1.,  2.,  3.])

Generating Matrices

In [5]:
# Unlike MATLAB, Python by default generates vectors, NOT matrices!
zero_vector = np.zeros(3)
zero_vector
Out[5]:
array([ 0.,  0.,  0.])
In [6]:
# "np.zeros" and "np.ones" generate zeros and ones, respecitvely.
# They only take ONE input argument, which can be a number or a tuple:
zero_matrix = np.zeros( (3,3))
zero_matrix
Out[6]:
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
In [7]:
# Note: "np.random.randn" in contrast can use more than one input argument:
np.random.randn(3,2)
Out[7]:
array([[-1.036, -0.162],
       [-0.292, -1.07 ],
       [ 1.325,  1.29 ]])
In [8]:
# Here an example of how to conveniently generate a matrix of column vectors:

phi = np.deg2rad(np.arange(0,360,30))
sines = np.sin(phi)
cosines = np.cos(phi)

data_mat = np.column_stack((sines, cosines))

print(np.round(data_mat, 2))
[[ 0.    1.  ]
 [ 0.5   0.87]
 [ 0.87  0.5 ]
 [ 1.    0.  ]
 [ 0.87 -0.5 ]
 [ 0.5  -0.87]
 [ 0.   -1.  ]
 [-0.5  -0.87]
 [-0.87 -0.5 ]
 [-1.   -0.  ]
 [-0.87  0.5 ]
 [-0.5   0.87]]

Generate Row- and Column-vectors

In [9]:
# A row-vector can be generated like this ...
row_vector = np.array([1,2,3])
row_vector
Out[9]:
array([1, 2, 3])
In [10]:
# ... or equivalently like that
row_vector2 = np.r_[3,4,5]
row_vector2
Out[10]:
array([3, 4, 5], dtype=int32)
In [11]:
# I know the syntax for generating column-vectors are all a bit weird :(
col_vector = np.c_[[4,5,6]]
col_vector
Out[11]:
array([[4],
       [5],
       [6]])
In [12]:
# This one uses the command "np.newaxis" to generate a column vector ....
row_vector[..., np.newaxis]
Out[12]:
array([[1],
       [2],
       [3]])
In [13]:
# ... and here is how to use the "reshape" command: the "-1" means "however many there are":
np.reshape(row_vector, (-1,1))
Out[13]:
array([[1],
       [2],
       [3]])

Working with Vectors and Matrices

Rotation of a vector

In [14]:
# Rotation matrix for a rotation by 30 deg
alpha = np.deg2rad(30)
rot_mat = np.array([[np.cos(alpha), -np.sin(alpha)],
                    [np.sin(alpha), np.cos(alpha)]])

# Note that there are two ways to specify a matrix multiplication
vec = np.r_[1,0]
vec_rotated = rot_mat.dot(vec)
vec_rotated_2 = rot_mat @ vec # for Python >3.5

# Show the results
print(rot_mat)
print('I rotated {0} into {1}'.format(str(vec), str(vec_rotated)))
np.all(vec_rotated == vec_rotated_2)
[[ 0.866 -0.5  ]
 [ 0.5    0.866]]
I rotated [1 0] into [ 0.866  0.5  ]
Out[14]:
True

"Broadcasting"

In numpy, "broadcasting" is a convenient way of adding numbers or vectors to a matrix, is the dimensions match up.

Here, I show how to subtract the mean value from each column:

In [15]:
# Generate some data
data = np.arange(15).reshape((5,3))
data
Out[15]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])
In [16]:
# overall mean
np.mean(data)
Out[16]:
7.000
In [17]:
# mean over all rows
np.mean(data, axis=0)
Out[17]:
array([ 6.,  7.,  8.])
In [18]:
# Now we use "broadcasting" to subtract the mean of each column:
# if the second index matches, the operation is applied to each row:
data - np.mean(data, axis=0)
Out[18]:
array([[-6., -6., -6.],
       [-3., -3., -3.],
       [ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])
In [19]:
# This only works on the last index!
data - np.mean(data, axis=1)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-19-cf2430189ce1> in <module>()
      1 # This only works on the last index!
----> 2 data - np.mean(data, axis=1)

ValueError: operands could not be broadcast together with shapes (5,3) (5,)