Basics#


# importing numpy
import numpy as np

NumPy arrays#

a = np.array( [0, 1, 2, 3] )

# standard Python list
b = [0, 1, 2, 3]

print( a )
print( b )
[0 1 2 3]
[0, 1, 2, 3]
print( type(a) )
print( type(b) )
<class 'numpy.ndarray'>
<class 'list'>
print( a.ndim  )
print( a.shape )
print( a.size  )
1
(4,)
4
# define 2D array
a = np.array( [ [1, 2, 3],
                [4, 5, 6] ] )

print( a )
[[1 2 3]
 [4 5 6]]
print( a.ndim  )
print( a.shape )
print( a.size  )
2
(2, 3)
6
# iterating
for c in a:
    print( c )
[1 2 3]
[4 5 6]

Functions for creating arrays#

# evenly spaced with step size
a = np.arange(1, 10, 2)  # start, end (exclusive), step size

print( a )
[1 3 5 7 9]
# evenly spaced with number of steps
a = np.linspace(1, 9, 5) # start, end (inclusive), number of steps

print( a )
[1. 3. 5. 7. 9.]
# log-spaced
a = np.logspace(1, 4, 4)

print( a )
[   10.   100.  1000. 10000.]
# all ones
a = np.ones((2, 3))

print( a )
[[1. 1. 1.]
 [1. 1. 1.]]
# all zeros
a = np.zeros((3, 3))

print( a )
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]
# diagonal one
a = np.eye(3)

print( a )
print( np.diag(a) )
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
[1. 1. 1.]
# self-defined diagonal
a = np.diag( np.array([1,2,3]) )

print( a )
[[1 0 0]
 [0 2 0]
 [0 0 3]]
# using a self-defined function
def myfunc(i, j):
    return i*10 + j

a = np.fromfunction(myfunc, (3,3))

print(a)
[[ 0.  1.  2.]
 [10. 11. 12.]
 [20. 21. 22.]]

Data types#

int, float, complex, bool, string, etc. …

# integer
a = np.array([1, 2, 3], dtype=int)

print( a )
print( a.dtype )
[1 2 3]
int64
# float
a = np.array([1, 2, 3], dtype=float)

print( a )
print( a.dtype )
[1. 2. 3.]
float64
# complex
a = np.array([1, 2, 3], dtype=complex)

print( a )
print( a.dtype )
[1.+0.j 2.+0.j 3.+0.j]
complex128

Accessing Elements#

a = np.diag( np.linspace(1, 6, 3) )
print( a )
[[1.  0.  0. ]
 [0.  3.5 0. ]
 [0.  0.  6. ]]
print( a[2, 2] )
6.0
print( a[:, 0] )
[1. 0. 0.]
print( a[2, :] )
[0. 0. 6.]
a[2, 0] = 10.
print( a )
[[ 1.   0.   0. ]
 [ 0.   3.5  0. ]
 [10.   0.   6. ]]
print( a[:, 0] )
[ 1.  0. 10.]
print( a[2, :] )
[10.  0.  6.]

Slicing#

a = np.arange(10)
print( a )
[0 1 2 3 4 5 6 7 8 9]
print( a[5:] )
[5 6 7 8 9]
print( a[5:7] )
[5 6]
print( a[2:10:2] )
[2 4 6 8]
print( a[::-1] )
[9 8 7 6 5 4 3 2 1 0]

print( a[ [2,5] ] )
[2 5]

Reshaping, Stacking, Concatenating#

# standard 1D array
a = np.arange(0, 12)
print( a )
[ 0  1  2  3  4  5  6  7  8  9 10 11]
# create a 2D array out of an 1D one
a = np.arange(0, 12).reshape(3, 4)
print( a )
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
# create a 3D array out of an 1D one
a = np.arange(0, 12).reshape(3, 2, 2)
print( a )
[[[ 0  1]
  [ 2  3]]

 [[ 4  5]
  [ 6  7]]

 [[ 8  9]
  [10 11]]]
# transposing
a = np.arange(0, 12).reshape(3,4)

print( a )

print( np.transpose( a ) )

print( a.T )
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[ 0  4  8]
 [ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]]
[[ 0  4  8]
 [ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]]

Stacking (easy concatenation)#

a = np.arange(0, 4).reshape(2,2)
b = np.arange(4, 8).reshape(2,2)

print( a )
print( b )
[[0 1]
 [2 3]]
[[4 5]
 [6 7]]
# vertical stack
c = np.vstack( (a, b) )
print( c )
[[0 1]
 [2 3]
 [4 5]
 [6 7]]
# horizontal stack
c = np.hstack( (a, b) )
print( c )
[[0 1 4 5]
 [2 3 6 7]]

Concatenating#

a = np.arange(0, 4).reshape(2, 2)
b = np.arange(4, 8).reshape(2, 2)

print( a )
print( b )
[[0 1]
 [2 3]]
[[4 5]
 [6 7]]
# vertical stack
c = np.concatenate((a, b), axis=0)
print( c )
[[0 1]
 [2 3]
 [4 5]
 [6 7]]
# horizontal stack
c = np.concatenate((a, b), axis=1)
print( c )
[[0 1 4 5]
 [2 3 6 7]]

Element-wise Operations#

Numerical Operations#

# define array
a = np.array( [0, 0.5, 1.0, 1.5, 2.0] )
print( a )
[0.  0.5 1.  1.5 2. ]
# subtract a float
print( a - 1.0 )
[-1.  -0.5  0.   0.5  1. ]
# square all elements
print( a**2 )
[0.   0.25 1.   2.25 4.  ]
# calculate sin of all elements
print( np.cos(a * np.pi) )
[ 1.0000000e+00  6.1232340e-17 -1.0000000e+00 -1.8369702e-16
  1.0000000e+00]
# calculate exp of all elements
print( np.exp(a) )
[1.         1.64872127 2.71828183 4.48168907 7.3890561 ]
# calculate sqrt of all elements
print( np.sqrt(a) )
[0.         0.70710678 1.         1.22474487 1.41421356]

Numpy Timings!#

# with Numpy
a = np.arange(10000)
%timeit b = a**2.0
21.8 μs ± 197 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
# without Numpy
a = range(10000)
%timeit b = [ i**2.0 for i in a ]
1.96 ms ± 10.8 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Comparisons / Conditional Operators#

# define array
a = np.array( [1, 2, 3, 4] )

# compare each element with a single number
print( a == 2 )
[False  True False False]
b = np.array( [1, 0, 3, 7])

# compare arrays element-wise
print( a == b )
[ True False  True False]
# compare arrays element-wise
print( a < b )
[False False False  True]

Basic Reductions#

# create a 2D array
a = np.arange(0, 12).reshape(3, 4)
print( a )
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
# over-all sum
print( np.sum(a) )
66
# row / col-wise sums
print( np.sum(a, axis=0) )
print( np.sum(a, axis=1) )
[12 15 18 21]
[ 6 22 38]
# find global min / max
print( np.min(a) )
print( np.max(a) )
0
11
# row / col-wise min/max
print( np.min(a, axis=0) )
print( np.min(a, axis=1) )
[0 1 2 3]
[0 4 8]
# get indices of the corresponding min / max
a = np.array([1,6,-3,0,-7,5])
print( a )
[ 1  6 -3  0 -7  5]
print( np.argmin(a) )
4
print( np.argmax(a) )
1

Sorting#

a = np.array([[4, 3, 1], 
              [1, 2, 5]])
print( a )
[[4 3 1]
 [1 2 5]]
# sort col-wise
print( np.sort(a, axis=0) )
[[1 2 1]
 [4 3 5]]
# sort row-wise
print( np.sort(a, axis=1) )
[[1 3 4]
 [1 2 5]]

Searching#

# select just some specific data
a = np.linspace(1, 10, 19)

print( a )
[ 1.   1.5  2.   2.5  3.   3.5  4.   4.5  5.   5.5  6.   6.5  7.   7.5
  8.   8.5  9.   9.5 10. ]
# find indices for a certain condition
ind = np.where( a < 6 )

print( ind ) 
(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),)
# print this specific data set
print( a[ ind ] )
[1.  1.5 2.  2.5 3.  3.5 4.  4.5 5.  5.5]
# find indices for multiple conditions
ind = np.where( (a < 6) & (a > 2) )

print( a[ ind ] )
[2.5 3.  3.5 4.  4.5 5.  5.5]

Shallow & Deep Copies / Views#

Warning

Be carefull with lists and arrays and their copies!

# define a simple list
a = [1, 2, 3]
# and a copy of it
b = a

print( "a:", a)
print( "b:", b)
a:
 [1, 2, 3]
b: [1, 2, 3]
# now edit first element of a
a[0] = 100

print( "a:", a)
a: [100, 2, 3]
print( "b:", b)
b: [100, 2, 3]
a = np.arange(0,8)
print( a )
[0 1 2 3 4 5 6 7]

Warning

A simple assignment will not create a copy!

b = a

# reshape b
b.shape = (2, 4)

# print both
print( a )
print( b )
[[0 1 2 3]
 [4 5 6 7]]
[[0 1 2 3]
 [4 5 6 7]]
# check if a and b are the same objects
print( b is a )
True
a = np.arange(0, 8)
print( a )
[0 1 2 3 4 5 6 7]
# create a "view" / also called "shallow copy"
b = a.view()

# edit the view
b.shape = (2, 4)

# print both
print( a )
print( b )
[0 1 2 3 4 5 6 7]
[[0 1 2 3]
 [4 5 6 7]]
# check if a and b are the same objects
print( b is a )
False
# edit an element of the shallow copy / view
b[0, 0] = -100

# print both
print( a )
print( b )
[-100    1    2    3    4    5    6    7]
[[-100    1    2    3]
 [   4    5    6    7]]
a = np.arange(0,8)
print( a )
[0 1 2 3 4 5 6 7]
# create a proper / deep copy
b = a.copy()

# edit the view
b.shape = (2, 4)

# print both
print( a )
print( b )
[0 1 2 3 4 5 6 7]
[[0 1 2 3]
 [4 5 6 7]]
# check if a and b are the same objects
print( b is a )
False
# edit an element of the shallow copy / view
b[0,0] = -100

# print both
print( a )
print( b )
[0 1 2 3 4 5 6 7]
[[-100    1    2    3]
 [   4    5    6    7]]