Importing


In [62]:
import numpy as np

Numpy arrays


In [63]:
a = np.array([1, 2, 3, 4, 5], float)
a


Out[63]:
array([ 1.,  2.,  3.,  4.,  5.])

In [64]:
b = np.array([9, 8, 9], int)
print(b.dtype)


int64

Numpy arrays behave similar to Python arrays


In [65]:
print(a[2:]) # all elements after the 2nd
print(a[-1]) # last element
print(a[2:4]) # slice 3rd to 4th
print(a[::2]) # every second element
a[0] = 5 
print(a)


[ 3.  4.  5.]
5.0
[ 3.  4.]
[ 1.  3.  5.]
[ 5.  2.  3.  4.  5.]

In [66]:
# iteration
for elem in a:
    print(elem)


5.0
2.0
3.0
4.0
5.0

Multi-dimensional arrays


In [67]:
A = np.array([[1,2,3], [4,5,6], [7,8,9]])
A


Out[67]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [68]:
print(A[0, 0]) # access single element
print(A[2, :]) # access 3rd row
print(A[:, 0]) # access first column
print(A[::2, :]) # get every second row


1
[7 8 9]
[1 4 7]
[[1 2 3]
 [7 8 9]]

Slicing


In [69]:
a = np.array(range(15))
print(a[1:10:2]) # every second elemtn from second to 10th
a[1::2] = 0 # set every second element to zero
print(a)


[1 3 5 7 9]
[ 0  0  2  0  4  0  6  0  8  0 10  0 12  0 14]

Array dimensions


In [38]:
print(len(A))     # length of 1st dimension
print(A.shape)    # shape of the arrays


3
(3, 3)

Check occurrence


In [39]:
print(2 in A)
print(13 in A)


True
False

Changing the shape of an array


In [70]:
c = np.array([1, 2, 3, 4, 5, 6])
print(c)
c.reshape((3, 2)) # reshape takes a dimension tuple as input (#rows,#cols)


[1 2 3 4 5 6]
Out[70]:
array([[1, 2],
       [3, 4],
       [5, 6]])

Attention: deep-copy vs. shallow-copy


In [71]:
a = np.array([1, 2, 3])
b = a
c = a.copy()
a[0] = 6
print(a)
print(b)
print(c)


[6 2 3]
[6 2 3]
[1 2 3]

Further array functions


In [13]:
# convert to python list
a.tolist()

# fill up with new value
a.fill(12)

print(A)
print(A.transpose()) # transpose matrix
print(A.T)           # same as A.transpose()


[[1 2 3]
 [4 5 6]
 [7 8 9]]
[[1 4 7]
 [2 5 8]
 [3 6 9]]
[[1 4 7]
 [2 5 8]
 [3 6 9]]

In [72]:
# concatenate arrays
B = A.transpose()

print(np.concatenate((A, B))) # concatenate vertically
print(np.concatenate((A, B), axis=1)) # concatenate horizontally


[[1 2 3]
 [4 5 6]
 [7 8 9]
 [1 4 7]
 [2 5 8]
 [3 6 9]]
[[1 2 3 1 4 7]
 [4 5 6 2 5 8]
 [7 8 9 3 6 9]]

Convenient functions to construct arrays


In [15]:
# equally spaced values within an interval: arange( start, stop, step )
np.arange(0, 5, 0.1)


Out[15]:
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ,
        1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,  1.9,  2. ,  2.1,
        2.2,  2.3,  2.4,  2.5,  2.6,  2.7,  2.8,  2.9,  3. ,  3.1,  3.2,
        3.3,  3.4,  3.5,  3.6,  3.7,  3.8,  3.9,  4. ,  4.1,  4.2,  4.3,
        4.4,  4.5,  4.6,  4.7,  4.8,  4.9])

In [73]:
# alternative version: linspace(start, stop, no_points)
np.linspace(0, 5, 50)


Out[73]:
array([ 0.        ,  0.10204082,  0.20408163,  0.30612245,  0.40816327,
        0.51020408,  0.6122449 ,  0.71428571,  0.81632653,  0.91836735,
        1.02040816,  1.12244898,  1.2244898 ,  1.32653061,  1.42857143,
        1.53061224,  1.63265306,  1.73469388,  1.83673469,  1.93877551,
        2.04081633,  2.14285714,  2.24489796,  2.34693878,  2.44897959,
        2.55102041,  2.65306122,  2.75510204,  2.85714286,  2.95918367,
        3.06122449,  3.16326531,  3.26530612,  3.36734694,  3.46938776,
        3.57142857,  3.67346939,  3.7755102 ,  3.87755102,  3.97959184,
        4.08163265,  4.18367347,  4.28571429,  4.3877551 ,  4.48979592,
        4.59183673,  4.69387755,  4.79591837,  4.89795918,  5.        ])

In [74]:
# generate 1 or 0-arrays
print(np.ones((2, 3)))
print(np.zeros((3, 4)))


[[ 1.  1.  1.]
 [ 1.  1.  1.]]
[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]

In [43]:
# construct an array with a similar shape to another one
np.zeros_like(A)


Out[43]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

In [44]:
# identity matrix
Id = np.identity(4)
Id


Out[44]:
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])

Linear algebra in numpy


In [75]:
A = np.array([[1, 2], [6, 7]])
np.linalg.det(A) # determinant
np.linalg.eig(A) # eigenvalues and eigenvectors
np.linalg.inv(A) # matrix inverse
np.linalg.svd(A) # singular value decomposition


Out[75]:
(array([[-0.22975292, -0.97324899],
        [-0.97324899,  0.22975292]]),
 array([ 9.47213595,  0.52786405]),
 array([[-0.64074744, -0.76775173],
        [ 0.76775173, -0.64074744]]))

numpy mathematics

All operations on arrays are elementwise per default


In [46]:
A = np.array([[1, 2], [3, 4]])
B = np.array([[0, 1], [1, 0]])
A + B
A - B
A * B
B / A
A ** B


Out[46]:
array([[1, 2],
       [3, 1]])

smaller arrays are broadcasted automatically


In [45]:
A = np.ones((3, 3))
c = np.array([1, 2, 3])
# per default arrays are added row-wise
A + c
# like this col-wise
A + c[:, np.newaxis]


Out[45]:
array([[ 2.,  2.,  2.],
       [ 3.,  3.,  3.],
       [ 4.,  4.,  4.]])

useful array functions


In [48]:
# element-wise functions
np.sqrt(a) # square root
np.sign(a) # sign
np.log(a) # natural logarithm
np.log10(a) # decadic logarithm
np.exp(a) #exponential
np.sin(a) # trigonometric (also cos, tan, arcsin, arccos, arctan)

# non-element-wise
a.sum() # sum of all elements 
a.prod() # product of all elements
a.mean() # mean
a.var() # variance
a.std() # standard deviation
a.max() # maximum
a.min() # minimum
a.sort()

np.unique([1, 1, 3, 3, 5]) # get unique elements


Out[48]:
array([1, 3, 5])

Matrix multiplication


In [49]:
A = np.array([[0, 1], [1, 0]])
v = np.array([6, 7])
np.dot(A, v) # matrix product


Out[49]:
array([7, 6])

Advaned array acessing


In [50]:
a = np.array([1, 6, 3, 4, 9, 6, 7, 3, 2, 4, 5])
a[a > 4] # get all elements larger than 4
a[np.logical_and(a > 4, a < 12)]

# acessing via index
indices = [1, 3]
a[indices]


Out[50]:
array([6, 4])

Scipy

Scipy is a collection of useful scientific algorithms

  • scipy.integrate
  • scipy.optimize
  • scipy.interpolate
  • etc...

In [51]:
import scipy as sp 
import scipy.optimize

In [52]:
from matplotlib import pyplot as plt
plt.style.use('ggplot')
%matplotlib inline

Example 1: numerical minimization of a function


In [76]:
# define a function
def myfunc(x):
    return (3 + x) * (3 - x)  * -12


# minimize using scipy
sp.optimize.minimize_scalar(myfunc)


Out[76]:
     fun: -108.0
    nfev: 39
     nit: 38
 success: True
       x: -3.195989243713537e-11

In [54]:
# plot the function 
x = np.arange(-100, 100, 1)
plt.plot(x, myfunc(x))


Out[54]:
[<matplotlib.lines.Line2D at 0x107ef02b0>]

Example 2: numerical integration

Consider a growing bacterial population with a doubling time of 2 hours

this means that the growth rate is $$ k_g = \frac {ln( 2 )} {2} = 0.34657359027997264 $$

and the growth model: $$ \frac {dx} {dt} = k_g \cdot x $$

lets integrate this ODE using scipy.integrate.odeint


In [57]:
import scipy.integrate

k_g = np.log(2) / 2
x0 = 1e-5
time = np.arange(0, 10, 1)

def dxdt(x, t):
    return k_g * x

result = scipy.integrate.odeint(dxdt, x0, time)

plt.plot(time, result)


Out[57]:
[<matplotlib.lines.Line2D at 0x1081ebe80>]

Compare exact and numerical solutions


In [58]:
exact = x0 * np.exp(k_g * time)
exact - result.T

plt.plot(time, (exact - result.T).T)


Out[58]:
[<matplotlib.lines.Line2D at 0x1082efba8>]

In [ ]: