Jupyter Snippet NP ch02-code-listing

Jupyter Snippet NP ch02-code-listing

Chapter 2: Vectors, matrices and multidimensional arrays

Robert Johansson

Source code listings for Numerical Python - Scientific Computing and Data Science Applications with Numpy, SciPy and Matplotlib (ISBN 978-1-484242-45-2).

import numpy as np

The NumPy array object

data = np.array([[1, 2], [3, 4], [5, 6]])
type(data)
numpy.ndarray
data
array([[1, 2],
       [3, 4],
       [5, 6]])
data.ndim
2
data.shape
(3, 2)
data.size
6
data.dtype
dtype('int64')
data.nbytes
48

Data types

np.array([1, 2, 3], dtype=np.int)
array([1, 2, 3])
np.array([1, 2, 3], dtype=np.float)
array([ 1.,  2.,  3.])
np.array([1, 2, 3], dtype=np.complex)
array([ 1.+0.j,  2.+0.j,  3.+0.j])
data = np.array([1, 2, 3], dtype=np.float)
data
array([ 1.,  2.,  3.])
data.dtype
dtype('float64')
data = np.array([1, 2, 3], dtype=np.int)
data.dtype
dtype('int64')
data
array([1, 2, 3])
data = np.array([1, 2, 3], dtype=np.float)
data
array([ 1.,  2.,  3.])
data.astype(np.int)
array([1, 2, 3])
d1 = np.array([1, 2, 3], dtype=float)
d2 = np.array([1, 2, 3], dtype=complex)
d1 + d2
array([ 2.+0.j,  4.+0.j,  6.+0.j])
(d1 + d2).dtype
dtype('complex128')
np.sqrt(np.array([-1, 0, 1]))
/Users/rob/miniconda/envs/py3.6-npm-e2/lib/python3.6/site-packages/ipykernel_launcher.py:1: RuntimeWarning: invalid value encountered in sqrt
  """Entry point for launching an IPython kernel.





array([ nan,   0.,   1.])
np.sqrt(np.array([-1, 0, 1], dtype=complex))
array([ 0.+1.j,  0.+0.j,  1.+0.j])

Real and imaginary parts

data = np.array([1, 2, 3], dtype=complex)
data
array([ 1.+0.j,  2.+0.j,  3.+0.j])
data.real
array([ 1.,  2.,  3.])
data.imag
array([ 0.,  0.,  0.])

Creating arrays

Arrays created from lists and other array-like objects

np.array([1, 2, 3, 4])
array([1, 2, 3, 4])
data.ndim
1
data.shape
(3,)
np.array([[1, 2], [3, 4]])
array([[1, 2],
       [3, 4]])
data.ndim
1
data.shape
(3,)

Arrays filled with constant values

np.zeros((2, 3))
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
np.ones(4)
array([ 1.,  1.,  1.,  1.])
data = np.ones(4)
data.dtype
dtype('float64')
data = np.ones(4, dtype=np.int64)
data.dtype
dtype('int64')
x1 = 5.4 * np.ones(10)
x2 = np.full(10, 5.4)
x1 = np.empty(5)
x1.fill(3.0)
x1
array([ 3.,  3.,  3.,  3.,  3.])
x2 = np.full(5, 3.0)
x2
array([ 3.,  3.,  3.,  3.,  3.])

Arrays filled with incremental sequences

np.arange(0.0, 10, 1)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
np.linspace(0, 10, 11)
array([  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.])

Arrays filled with logarithmic sequences

np.logspace(0, 2, 5)  # 5 data points between 10**0=1 to 10**2=100
array([   1.        ,    3.16227766,   10.        ,   31.6227766 ,  100.        ])

Mesh-grid arrays

x = np.array([-1, 0, 1])
y = np.array([-2, 0, 2])
X, Y = np.meshgrid(x, y)
X
array([[-1,  0,  1],
       [-1,  0,  1],
       [-1,  0,  1]])
Y
array([[-2, -2, -2],
       [ 0,  0,  0],
       [ 2,  2,  2]])
Z = (X + Y) ** 2
Z
array([[9, 4, 1],
       [1, 0, 1],
       [1, 4, 9]])

Creating uninitialized arrays

np.empty(3, dtype=np.float)
array([ 1.,  2.,  3.])

Creating arrays with properties of other arrays

def f(x):
    y = np.ones_like(x)
    # compute with x and y
    return y

Creating matrix arrays

np.identity(4)
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])
np.eye(3, k=1)
array([[ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  0.]])
np.eye(3, k=-1)
array([[ 0.,  0.,  0.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.]])
np.diag(np.arange(0, 20, 5))
array([[ 0,  0,  0,  0],
       [ 0,  5,  0,  0],
       [ 0,  0, 10,  0],
       [ 0,  0,  0, 15]])

Index and slicing

One-dimensional arrays

a = np.arange(0, 11)
a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
a[0]  # the first element
0
a[-1] # the last element
10
a[4]  # the fifth element, at index 4
4
a[1:-1]
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
a[1:-1:2]
array([1, 3, 5, 7, 9])
a[:5]
array([0, 1, 2, 3, 4])
a[-5:]
array([ 6,  7,  8,  9, 10])
a[::-2]

array([10,  8,  6,  4,  2,  0])

Multidimensional arrays

f = lambda m, n: n + 10 * m
A = np.fromfunction(f, (6, 6), dtype=int)
A
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
A[:, 1]  # the second column
array([ 1, 11, 21, 31, 41, 51])
A[1, :]  # the second row
array([10, 11, 12, 13, 14, 15])
A[:3, :3]  # upper half diagonal block matrix
array([[ 0,  1,  2],
       [10, 11, 12],
       [20, 21, 22]])
A[3:, :3]  # lower left off-diagonal block matrix
array([[30, 31, 32],
       [40, 41, 42],
       [50, 51, 52]])
A[::2, ::2]  # every second element starting from 0, 0
array([[ 0,  2,  4],
       [20, 22, 24],
       [40, 42, 44]])
A[1::2, 1::3]  # every second element starting from 1, 1
array([[11, 14],
       [31, 34],
       [51, 54]])

Views

B = A[1:5, 1:5]
B
array([[11, 12, 13, 14],
       [21, 22, 23, 24],
       [31, 32, 33, 34],
       [41, 42, 43, 44]])
B[:, :] = 0
A
array([[ 0,  1,  2,  3,  4,  5],
       [10,  0,  0,  0,  0, 15],
       [20,  0,  0,  0,  0, 25],
       [30,  0,  0,  0,  0, 35],
       [40,  0,  0,  0,  0, 45],
       [50, 51, 52, 53, 54, 55]])
C = B[1:3, 1:3].copy()
C
array([[0, 0],
       [0, 0]])
C[:, :] = 1  # this does not affect B since C is a copy of the view B[1:3, 1:3]
C
array([[1, 1],
       [1, 1]])
B
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

Fancy indexing and Boolean-valued indexing

A = np.linspace(0, 1, 11)
A[np.array([0, 2, 4])]
array([ 0. ,  0.2,  0.4])
A[[0, 2, 4]]
array([ 0. ,  0.2,  0.4])
A > 0.5 
array([False, False, False, False, False, False,  True,  True,  True,
        True,  True], dtype=bool)
A[A > 0.5]
array([ 0.6,  0.7,  0.8,  0.9,  1. ])
A = np.arange(10)
A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
indices = [2, 4, 6]
B = A[indices]
B[0] = -1  # this does not affect A
A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
A[indices] = -1
A
array([ 0,  1, -1,  3, -1,  5, -1,  7,  8,  9])
A = np.arange(10)
B = A[A > 5]
B[0] = -1  # this does not affect A
A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
A[A > 5] = -1
A
array([ 0,  1,  2,  3,  4,  5, -1, -1, -1, -1])

Reshaping and resizing

data = np.array([[1, 2], [3, 4]])
np.reshape(data, (1, 4))
array([[1, 2, 3, 4]])
data.reshape(4)
array([1, 2, 3, 4])
data = np.array([[1, 2], [3, 4]])
data
array([[1, 2],
       [3, 4]])
data.flatten()
array([1, 2, 3, 4])
data.flatten().shape
(4,)
data = np.arange(0, 5)
column = data[:, np.newaxis]
column
array([[0],
       [1],
       [2],
       [3],
       [4]])
row = data[np.newaxis, :]
row
array([[0, 1, 2, 3, 4]])
data = np.arange(5)
data
array([0, 1, 2, 3, 4])
np.vstack((data, data, data))
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])
data = np.arange(5)
data
array([0, 1, 2, 3, 4])
np.hstack((data, data, data))
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
data = data[:, np.newaxis]
np.hstack((data, data, data))
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2],
       [3, 3, 3],
       [4, 4, 4]])

Vectorized expressions

Arithmetic operations

x = np.array([[1, 2], [3, 4]]) 
y = np.array([[5, 6], [7, 8]])
x + y
array([[ 6,  8],
       [10, 12]])
y - x
array([[4, 4],
       [4, 4]])
x * y
array([[ 5, 12],
       [21, 32]])
y / x
array([[ 5.        ,  3.        ],
       [ 2.33333333,  2.        ]])
x * 2
array([[2, 4],
       [6, 8]])
2 ** x
array([[ 2,  4],
       [ 8, 16]])
y / 2
array([[ 2.5,  3. ],
       [ 3.5,  4. ]])
(y / 2).dtype
dtype('float64')
x = np.array([1, 2, 3, 4]).reshape(2,2)
z = np.array([1, 2, 3, 4])
x / z
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-146-c325a0617380> in <module>()
----> 1 x / z


ValueError: operands could not be broadcast together with shapes (2,2) (4,) 
z = np.array([[2, 4]])
z
array([[2, 4]])
z.shape
(1, 2)
x / z
array([[ 0.5,  0.5],
       [ 1.5,  1. ]])
zz = np.concatenate([z, z], axis=0)
zz
array([[2, 4],
       [2, 4]])
x / zz
array([[ 0.5,  0.5],
       [ 1.5,  1. ]])
z = np.array([[2], [4]])
z.shape
(2, 1)
x / z
array([[ 0.5 ,  1.  ],
       [ 0.75,  1.  ]])
zz = np.concatenate([z, z], axis=1)
zz
array([[2, 2],
       [4, 4]])
x / zz
array([[ 0.5 ,  1.  ],
       [ 0.75,  1.  ]])
x = np.array([[1, 3], [2, 4]])
x = x + y
x
array([[ 6,  9],
       [ 9, 12]])
x = np.array([[1, 3], [2, 4]])
x += y
x
array([[ 6,  9],
       [ 9, 12]])

Elementwise functions

x = np.linspace(-1, 1, 11)
x
array([-1. , -0.8, -0.6, -0.4, -0.2,  0. ,  0.2,  0.4,  0.6,  0.8,  1. ])
y = np.sin(np.pi * x)
np.round(y, decimals=4)
array([-0.    , -0.5878, -0.9511, -0.9511, -0.5878,  0.    ,  0.5878,
        0.9511,  0.9511,  0.5878,  0.    ])
np.add(np.sin(x) ** 2, np.cos(x) ** 2)
array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])
np.sin(x) ** 2 + np.cos(x) ** 2
array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])
def heaviside(x):
    return 1 if x > 0 else 0
heaviside(-1)
0
heaviside(1.5)
1
x = np.linspace(-5, 5, 11)
heaviside(x)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-172-52f34380192d> in <module>()
----> 1 heaviside(x)


<ipython-input-168-68cdb49d4533> in heaviside(x)
      1 def heaviside(x):
----> 2     return 1 if x > 0 else 0


ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
heaviside = np.vectorize(heaviside)
heaviside(x)
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
def heaviside(x):
    return 1.0 * (x > 0)

Aggregate functions

data = np.random.normal(size=(15,15))
np.mean(data)
-0.090472669644641304
data.mean()
-0.090472669644641304
data = np.random.normal(size=(5, 10, 15))
data.sum(axis=0).shape
(10, 15)
data.sum(axis=(0, 2)).shape
(10,)
data.sum()
25.869033203350682
data = np.arange(1,10).reshape(3,3)
data
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
data.sum()
45
data.sum(axis=0)
array([12, 15, 18])
data.sum(axis=1)
array([ 6, 15, 24])

Boolean arrays and conditional expressions

a = np.array([1, 2, 3, 4])
b = np.array([4, 3, 2, 1])
a < b
array([ True,  True, False, False], dtype=bool)
np.all(a < b)
False
np.any(a < b)
True
if np.all(a < b):
    print("All elements in a are smaller than their corresponding element in b")
elif np.any(a < b):
    print("Some elements in a are smaller than their corresponding elemment in b")
else:
    print("All elements in b are smaller than their corresponding element in a")
Some elements in a are smaller than their corresponding elemment in b
x = np.array([-2, -1, 0, 1, 2])
x > 0
array([False, False, False,  True,  True], dtype=bool)
1 * (x > 0)
array([0, 0, 0, 1, 1])
x * (x > 0)
array([0, 0, 0, 1, 2])
def pulse(x, position, height, width):
    return height * (x >= position) * (x <= (position + width))
x = np.linspace(-5, 5, 11)
pulse(x, position=-2, height=1, width=5)
array([0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0])
pulse(x, position=1, height=1, width=5)
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
def pulse(x, position, height, width):
    return height * np.logical_and(x >= position, x <= (position + width))
x = np.linspace(-4, 4, 9)
np.where(x < 0, x**2, x**3)
array([ 16.,   9.,   4.,   1.,   0.,   1.,   8.,  27.,  64.])
np.select([x < -1, x < 2, x >= 2],
          [x**2  , x**3 , x**4])
array([  16.,    9.,    4.,   -1.,    0.,    1.,   16.,   81.,  256.])
np.choose([0, 0, 0, 1, 1, 1, 2, 2, 2], 
          [x**2,    x**3,    x**4])
array([  16.,    9.,    4.,   -1.,    0.,    1.,   16.,   81.,  256.])
x[abs(x) > 2]
array([-4., -3.,  3.,  4.])
np.nonzero(abs(x) > 2)
(array([0, 1, 7, 8]),)
x[np.nonzero(abs(x) > 2)]
array([-4., -3.,  3.,  4.])

Set operations

a = np.unique([1,2,3,3])
b = np.unique([2,3,4,4,5,6,5])
np.in1d(a, b)
array([False,  True,  True], dtype=bool)
1 in a
True
1 in b
False
np.all(np.in1d(a, b))
False
np.union1d(a, b)
array([1, 2, 3, 4, 5, 6])
np.intersect1d(a, b)
array([2, 3])
np.setdiff1d(a, b)
array([1])
np.setdiff1d(b, a)
array([4, 5, 6])

Operations on arrays

data = np.arange(9).reshape(3, 3)
data
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
np.transpose(data)
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])
data = np.random.randn(1, 2, 3, 4, 5)
data.shape
(1, 2, 3, 4, 5)
data.T.shape
(5, 4, 3, 2, 1)

Matrix and vector operations

A = np.arange(1, 7).reshape(2, 3)
A
array([[1, 2, 3],
       [4, 5, 6]])
B = np.arange(1, 7).reshape(3, 2)
B
array([[1, 2],
       [3, 4],
       [5, 6]])
np.dot(A, B)
array([[22, 28],
       [49, 64]])
np.dot(B, A)
array([[ 9, 12, 15],
       [19, 26, 33],
       [29, 40, 51]])
A = np.arange(9).reshape(3, 3)
A
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
x = np.arange(3)
x
array([0, 1, 2])
np.dot(A, x)
array([ 5, 14, 23])
A.dot(x)
array([ 5, 14, 23])
A = np.random.rand(3,3)
B = np.random.rand(3,3)
Ap = B @ A @ np.linalg.inv(B)
Ap
array([[-0.15628289,  1.01950542,  0.54368897],
       [ 0.1421288 ,  0.60925824,  0.90360847],
       [ 0.03321325,  0.63335306,  0.47040536]])
Ap = np.dot(B, np.dot(A, np.linalg.inv(B)))
Ap
array([[-0.15628289,  1.01950542,  0.54368897],
       [ 0.1421288 ,  0.60925824,  0.90360847],
       [ 0.03321325,  0.63335306,  0.47040536]])
Ap = B.dot(A.dot(np.linalg.inv(B)))
Ap
array([[-0.15628289,  1.01950542,  0.54368897],
       [ 0.1421288 ,  0.60925824,  0.90360847],
       [ 0.03321325,  0.63335306,  0.47040536]])
A = np.matrix(A)
B = np.matrix(B)
Ap = B * A * B.I
A = np.asmatrix(A)
B = np.asmatrix(B)
Ap = B * A * B.I
Ap = np.asarray(Ap)
Ap
array([[-0.15628289,  1.01950542,  0.54368897],
       [ 0.1421288 ,  0.60925824,  0.90360847],
       [ 0.03321325,  0.63335306,  0.47040536]])
np.inner(x, x)
5
np.dot(x, x)
5
y = x[:, np.newaxis]
y
array([[0],
       [1],
       [2]])
np.dot(y.T, y)
array([[5]])
x = np.array([1, 2, 3])
np.outer(x, x) 
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])
np.kron(x, x) 
array([1, 2, 3, 2, 4, 6, 3, 6, 9])
np.kron(x[:, np.newaxis], x[np.newaxis, :])
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])
np.kron(np.ones((2,2)), np.identity(2))
array([[ 1.,  0.,  1.,  0.],
       [ 0.,  1.,  0.,  1.],
       [ 1.,  0.,  1.,  0.],
       [ 0.,  1.,  0.,  1.]])
np.kron(np.identity(2), np.ones((2,2)))
array([[ 1.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  1.],
       [ 0.,  0.,  1.,  1.]])
x = np.array([1, 2, 3, 4])
y = np.array([5, 6, 7, 8])
np.einsum("n,n", x, y)
70
np.inner(x, y)
70
A = np.arange(9).reshape(3, 3)
B = A.T
np.einsum("mk,kn", A, B)
array([[  5,  14,  23],
       [ 14,  50,  86],
       [ 23,  86, 149]])
np.alltrue(np.einsum("mk,kn", A, B) == np.dot(A, B))
True

Versions

%reload_ext version_information
%version_information numpy