This notebook contains tips and tricks of working with vectors and matrices:
author: Thomas Haslwanter, date: Feb-2017
# import standard packages
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import frange
# To make the display prettier
%precision 3
'%.3f'
# Note that with "arange" the last value is NOT included!
x = np.arange(1,5,0.5)
x
array([ 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
# "linspace" produces a given number of linearly spaced numbers
y = np.linspace(0,1,11)
y
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
# "frange" includes the last value
z = frange(1,3)
z
array([ 1., 2., 3.])
# Unlike MATLAB, Python by default generates vectors, NOT matrices!
zero_vector = np.zeros(3)
zero_vector
array([ 0., 0., 0.])
# "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
array([[ 0., 0., 0.], [ 0., 0., 0.], [ 0., 0., 0.]])
# Note: "np.random.randn" in contrast can use more than one input argument:
np.random.randn(3,2)
array([[-1.036, -0.162], [-0.292, -1.07 ], [ 1.325, 1.29 ]])
# 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]]
# A row-vector can be generated like this ...
row_vector = np.array([1,2,3])
row_vector
array([1, 2, 3])
# ... or equivalently like that
row_vector2 = np.r_[3,4,5]
row_vector2
array([3, 4, 5], dtype=int32)
# I know the syntax for generating column-vectors are all a bit weird :(
col_vector = np.c_[[4,5,6]]
col_vector
array([[4], [5], [6]])
# This one uses the command "np.newaxis" to generate a column vector ....
row_vector[..., np.newaxis]
array([[1], [2], [3]])
# ... and here is how to use the "reshape" command: the "-1" means "however many there are":
np.reshape(row_vector, (-1,1))
array([[1], [2], [3]])
# 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 ]
True
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:
# Generate some data
data = np.arange(15).reshape((5,3))
data
array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11], [12, 13, 14]])
# overall mean
np.mean(data)
7.000
# mean over all rows
np.mean(data, axis=0)
array([ 6., 7., 8.])
# 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)
array([[-6., -6., -6.], [-3., -3., -3.], [ 0., 0., 0.], [ 3., 3., 3.], [ 6., 6., 6.]])
# 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,)