12. Introduction to NumPy and Matplotlib I#

Last time#

  • Searching algorithms

  • Sorting algorithms

  • Lambda

  • Hash table

Today#

Python package: NumPy#

What is NumPy?#

  • Numerical Python (NumPy) is the fundamental package for scientific computing in Python.

  • It is an open source library that’s used in every fields of science and engineering. You can say that it is the universal standard for working with numerical data in Python.

  • Reference:

    1. NumPy documentation

    2. NumPy: the absolute basics for beginners


Installing NumPy#

  1. Activate your virtual environment

  2. Install NumPy

    pip install numpy
    

Array: numpy.ndarray#

  • A grid of values with the same data type (can be check via numpy.ndarray.dtype)

  • Indexed by a tuple of nonnegative integers

    • Rank: the number of dimensions (can be check via numpy.ndarray.ndim)

    • Shape: the size of the array along each dimension (can be check via numpy.ndarray.shape)

    • More array attributes: Refer to here

import numpy as np

a = np.arange(5)

print(a)
print("Type of a:", type(a))
print("Data type of a:", a.dtype)
print("Rank of a:", a.ndim)
print("Shape of a:", a.shape)

print("="*50)

b = np.ones((4,3), dtype=np.float16)

print(b)
print("Type of b:", type(b))
print("Data type of b:", b.dtype)
print("Rank of b:", b.ndim)
print("Shape of b:", b.shape)
[0 1 2 3 4]
Type of a: <class 'numpy.ndarray'>
Data type of a: int32
Rank of a: 1
Shape of a: (5,)
==================================================
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
Type of b: <class 'numpy.ndarray'>
Data type of b: float16
Rank of b: 2
Shape of b: (4, 3)

Important skill: read the documentation#


NumPy array vs. Python list#

  • Example 1: Add two arrays

# list
a = [1, 2, 3, 4, 5]
b = [-5, 3, 2, 0, 8]
print("a + b =", a + b)
print([v1+v2 for v1, v2 in zip(a, b)])
a + b = [1, 2, 3, 4, 5, -5, 3, 2, 0, 8]
[-4, 5, 5, 4, 13]
# numpy array
a = np.array([1, 2, 3, 4, 5])
b = np.array([-5, 3, 2, 0, 8])
print("a + b =", a + b)
a + b = [-4  5  5  4 13]
  • Example 2: Multiply two arrays element-wisely

# list
a = [1, 2, 3, 4, 5]
b = [-5, 3, 2, 0, 8]
# print("a * b =", a * b)
print([v1*v2 for v1, v2 in zip(a, b)])
[-5, 6, 6, 0, 40]
# numpy array
a = np.array([1, 2, 3, 4, 5])
b = np.array([-5, 3, 2, 0, 8])
print("a * b =", a * b)
a * b = [-5  6  6  0 40]

1D array#

  • Can be directly ceated by list or other methods

tmp = [1,3,5,7,9]
a = np.array(tmp)
b = np.zeros(5, dtype=np.int16)
c = np.ones((5,))
d = np.full_like(a, fill_value=5)

print("a:", a, "dtype:", a.dtype)
print("b:", b, "dtype:", b.dtype)
print("c:", c, "dtype:", c.dtype)
print("d:", d, "dtype:", d.dtype)
a: [1 3 5 7 9] dtype: int32
b: [0 0 0 0 0] dtype: int16
c: [1. 1. 1. 1. 1.] dtype: float64
d: [5 5 5 5 5] dtype: int32
  • Create evenly spaced numbers

  1. np.arange

a = np.arange(5)
b = np.arange(5,10)
c = np.arange(0,10,2)

print("a:", a, "dtype:", a.dtype)
print("b:", b, "dtype:", b.dtype)
print("c:", c, "dtype:", c.dtype)
a: [0 1 2 3 4] dtype: int32
b: [5 6 7 8 9] dtype: int32
c: [0 2 4 6 8] dtype: int32
  1. np.linspace

a = np.linspace(0, 4, 5)
b = np.linspace(start=-1, stop=1, num=5)
c = np.linspace(
    start=0, 
    stop=10, 
    num=5,
)

print("a:", a, "dtype:", a.dtype)
print("b:", b, "dtype:", b.dtype)
print("c:", c, "dtype:", c.dtype)
a: [0. 1. 2. 3. 4.] dtype: float64
b: [-1.  -0.5  0.   0.5  1. ] dtype: float64
c: [ 0.   2.5  5.   7.5 10. ] dtype: float64
  1. np.logspace and np.geomspace

    • Return numbers spaced evenly on a log scale.

a = np.logspace(start=0, stop=4, num=5, base=10.)
b = np.geomspace(start=1e0, stop=1e4, num=5)

print("a:", a, "dtype:", a.dtype)
print("b:", b, "dtype:", b.dtype)
a: [1.e+00 1.e+01 1.e+02 1.e+03 1.e+04] dtype: float64
b: [1.e+00 1.e+01 1.e+02 1.e+03 1.e+04] dtype: float64

Exercise 12.1#

  • Please create the following np.array:

Index

Array

1

[ 5  4  3  2  1  0 -1 -2 -3 -4]

2

[-100.  -80.  -60.  -40.  -20.    0.   20.   40.   60.   80.  100.]

3

[1.e-05 1.e-04 1.e-03 1.e-02 1.e-01 1.e+00 1.e+01 1.e+02]


Boolean indexing#

x = np.linspace(-5, 5, 11)

print("x:          ", x)
print("x >= 0:     ", x>=0)

x[x>=3] = 3
print("x[x>=3] = 3:", x)

print("np.where:   ", np.where(x>-2, 9, x))
print("np.clip:    ", np.clip(x, -2, 2))
x:           [-5. -4. -3. -2. -1.  0.  1.  2.  3.  4.  5.]
x >= 0:      [False False False False False  True  True  True  True  True  True]
x[x>=3] = 3: [-5. -4. -3. -2. -1.  0.  1.  2.  3.  3.  3.]
np.where:    [-5. -4. -3. -2.  9.  9.  9.  9.  9.  9.  9.]
np.clip:     [-2. -2. -2. -2. -1.  0.  1.  2.  2.  2.  2.]

Numerical operations on arrays#

  • Numpy provides a variety of mathematical functions

    • Trigonometric functions

      np.sin, np.cos, np.tan, np.arcsin, np.arccos, np.deg2rad, np.rad2deg

    • Hyperbolic functions

      np.sinh, np.cosh, np.tanh, np.arcsinh, np.arccosh, np.arctanh

    • Rounding

      np.around, np.floor, np.ceil, np.trunc, np.fix

    • Complex numbers

      np.angle, np.real, np.imag, np.conj

Python package: Matplotlib#

What is Matplotlib?#

  • A popular visualization library, most importantly, it is free and open source (vs. Matlab).

  • Good for visualizing 1D, 2D (or 3D) data

  • Support numpy.ndarray and list

  • Reference:

    1. Matplotlib documentation

    2. Learning matplotlib


Installing matplotlib#

  1. Activate your virtual environment

  2. Install matplotlib

    pip install matplotlib
    

Types of plotting in Matplotlib#

Supplement: Grid control

Draw a first plot#

  • Import module

import matplotlib.pyplot as plt
  • Imperative syntax

x = np.linspace(0, 2 * np.pi, 200)
y = np.sin(x)

plt.figure(1, figsize=(4,3), dpi=100)
plt.plot(x, y, label="sin(x)")
plt.title("My First Plot", fontsize=14, fontweight='bold')
plt.xlabel("x")
plt.ylabel("f(x)")
plt.grid(True)
plt.legend(loc="best")
plt.show()
../../_images/4a132ed52cc71f6654211a6f787c0d8db0002ba735a2ea39b78810b76f9a6ccb.png
  • Object-oriented syntax

fig = plt.figure(2, figsize=(4,3), dpi=100)
ax = fig.add_subplot(111)
ax.plot(x, y, label="sin(x)")
ax.set_title("My First Plot", fontsize=14, fontweight='bold')
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax.legend(loc='best')
ax.grid(True)
# fig.clear()
plt.show()
../../_images/4a132ed52cc71f6654211a6f787c0d8db0002ba735a2ea39b78810b76f9a6ccb.png

Anatomy of a figure#


Exercise 12.2: Plot a function#

  • Please write a program that can plot this function \(f(x)\)

\[\begin{split} \begin{equation} f(x) = \begin{cases} \sin{5x}, \; x < 0 \\ x^2+2x+4, \; 0 \le x < 1 \\ x^3, \; x \ge 1 \end{cases} \end{equation} \end{split}\]
  • Try to meet below’s figure


import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-3, 3, 201)
y = np.where(x < 0, np.sin(5*x), x)
y = np.where(((x >= 0) & (x < 1)), x**2+2*x+4, y)
y = np.where(x >= 1, x**3, y)

fig = plt.figure(figsize=(5, 4), dpi=100, layout="constrained", facecolor="white")
# ax = fig.add_axes((20,3,4,3))
ax = fig.add_subplot(111)
ax.plot(x, y, 'r', label="Exercise 1: f(x)")
ax.minorticks_on()
ax.xaxis.set_tick_params(rotation=50, labelsize=10)
ax.set_xlim(-3,3)
x_start, x_end = ax.get_xlim()
# ax.xaxis.set_ticks(np.arange(x_start, x_end, 0.5))
ax.xaxis.set_ticks(np.linspace(x_start, x_end, 13))
ax.set_xlabel("x", fontweight='bold')
ax.set_ylabel("f(x)", fontweight='bold')
ax.set_title("Exercise 1", fontweight='bold')
ax.grid(True)
# fig.tight_layout()
# fig.savefig('Exercise1.png')
plt.show()
../../_images/58f876592e1b20f86ad5da138b16f44a8c4bb2ce3668bde3aabb9cc605dba212.png

Polar plot#

  • Plot a curve on a polar axis.

  • Define \(r\) and \(\theta\) first.

theta = np.linspace(0, 2*np.pi, 1000)
r1 = 1 + np.sin(theta)
r2 = np.linspace(0, 2, 1000)

fig = plt.figure(figsize=(12,5), dpi=100, layout="constrained")

ax1 = fig.add_subplot(121)
ax1.plot(theta, r1, label="r1")
ax1.plot(theta, r2, label="r2")
ax1.set_xticks(np.linspace(0, 2*np.pi, 5))
ax1.grid(True)
ax1.set_title("Subplot 121")
ax1.set_xlabel(r"$\theta$", fontsize=15)
ax1.set_ylabel(r"$r$", fontsize=15)
ax1.legend()

ax2 = fig.add_subplot(122, projection='polar')
ax2.plot(theta, r1, label="r1")
ax2.plot(theta, r2, label="r2")
ax2.set_title("Subplot 122")
ax2.set_rticks(np.linspace(0,2,5))
ax2.set_rlabel_position(-90)
ax2.legend()

# fig.savefig("polar_plot.png", bbox_inches='tight', facecolor='white')

plt.show()
../../_images/888efb0432e219d28b6cd410053671f6ae32f6097b46f11a7c25e1ddf7f0c86a.png

Exercise 12.3: Plot a function#

  • Please write a program that can plot this function \(f(\theta)\)

\[ f(\theta) = a + b \times \sin^{2}(\theta - c) \]
  • Please try different combinations of (a, b, c)


Shaded plot#

freq = 440.0
period = 1 / freq

t = np.linspace(0, 2*period, 100)

c1 = np.sin(2*np.pi*freq*t)
c2 = np.sin(2*np.pi*freq/(2**(1/12))*t)

xticks = []
xticklabels = []
total_ticks = 9

for i in range(total_ticks):
    xticks.append(2*period/8*i)
    xticklabels.append("{:.2f}T".format(i/4))

fig, ax = plt.subplots(1, 1, figsize=(8, 3), dpi=100) 
ax.fill_between(t, y1=c1, y2=c2, where=None, color='green', alpha=0.1)
ax.plot(t, c1, label='A')
ax.plot(t, c2, label='G#')
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels)
# ax.set_xlim(t.max(), 0) # reverse x-axis
ax.legend()
ax.grid(True)
plt.show()
../../_images/d9a3826e9895b81615fc251c48b7257632d020b8d81b52a3676bd6b26a9580c1.png

Exercise 12.4: Shaded plot#

  • Please write a program that plots 2 sinusoidal curves with C4 and A4 frequencies.

\[ f_n = f_0 \times (\sqrt[12]{2})^n \]
  • Try to meet below’s figure


Scatter plot#

num = 100

theta = np.linspace(0, np.pi/2, num)

pdf = np.random.rand(num, num)
cir = np.array([np.cos(theta), np.sin(theta)])

colors = ['green', 'red']
labels = ['Uniform', 'Circle']
markers = ['^', 'x']

fig, ax = plt.subplots(1, 1, figsize=(4, 4), dpi=100) 

for color, name, marker, data in zip(colors, labels, markers, (pdf, cir)):
    ax.scatter(data[0], data[1], c=color, label=name, marker=marker)

ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.legend()
ax.grid(True)
plt.show()
../../_images/6b83adc51972af44dbb19b41c530d53fd1268108e6ae1474243c42ea18b76c6d.png

Boxplot#

  • Draw a box and whisker plot

  • Documentation

  • Syntax

    Axes.boxplot(self, x, notch=None, sym=None, vert=None, whis=None, 
                positions=None, widths=None, patch_artist=None, 
                bootstrap=None, usermedians=None, conf_intervals=None, 
                meanline=None, showmeans=None, showcaps=None, showbox=None, 
                showfliers=None, labels=None)
    
num = 100

pdf1 = np.random.rand(num)
pdf2 = np.random.randn(num)

fig = plt.figure(figsize=(6, 3))

ax1 = fig.add_subplot(131)
ax1.boxplot([pdf1, pdf2], meanline=True, showfliers=True)
ax1.set_xticklabels(["Uniform", "Gaussian"])

ax2 = fig.add_subplot(132)
ax2.boxplot([pdf1, pdf2], meanline=True, showfliers=False)
ax2.set_xticklabels(["Uniform", "Gaussian"])

ax3 = fig.add_subplot(133)
ax3.boxplot([pdf1, pdf2], patch_artist=True, meanline=True, showfliers=True)
ax3.set_xticklabels(["Uniform", "Gaussian"])

plt.show()
../../_images/1a9d0c0d7fc918aaa701871cd32dc1c59a47d311907e49b412aa9e1054c5c193.png

Histogram#

  • Compute and plot a histogram

  • Documentation

  • Syntax

    Axes.hist(x, bins=None, range=None, density=False, weights=None, 
            cumulative=False, bottom=None, histtype='bar', align='mid', 
            orientation='vertical', rwidth=None, log=False, color=None, 
            label=None, stacked=False, *, data=None, **kwargs)
    
num = 10000
rwidth = 1
nBins = 100
meanGaus, varGaus = 0.5, 0.1

pdf1 = np.random.rand(num)
pdf2 = varGaus*np.random.randn(num) + meanGaus

fig = plt.figure(figsize=(5,3), dpi=100)
ax = fig.add_subplot(111)

n1, bins1, patches1 = ax.hist(
    pdf1, 
    bins=nBins, 
    rwidth=rwidth, 
    facecolor='blue', 
    alpha=0.5, 
    align='mid', 
    label="Uniform distribution"
)
n2, bins2, patches2 = ax.hist(
    pdf2, 
    bins=nBins, 
    rwidth=rwidth, 
    facecolor='red', 
    alpha=0.5, 
    align='mid', 
    label="Gaussian distribution (mean = {}, var = {})".format(meanGaus, varGaus)
)

# ax.set_xlim([0, 1])
# ax.set_ylim([0, np.max(n2)*1.5])
ax.legend(loc="best")
ax.grid(True)

plt.show()
../../_images/afe16337e40e988ed73eebbdff192a0a444dd5829aed8f848427900c1263f879.png
Don't click this
Exercise 12.2
x = np.linspace(-3, 3, 201)
y = np.where(x < 0, np.sin(5*x), x)
y = np.where(((x >= 0) & (x < 1)), x**2+2*x+4, y)
y = np.where(x >= 1, x**3, y)

fig = plt.figure(figsize=(8, 5), dpi=100)
ax = fig.add_subplot()
ax.plot(x, y, 'r', label="Exercise 1: f(x)")
ax.set_xlim(-3,3)
ax.set_xlabel("x", fontweight='bold')
ax.set_ylabel("f(x)", fontweight='bold')
ax.set_title("Exercise 1", fontweight='bold')
plt.grid(True)
# fig.savefig('Exercise1.png', bbox_inches='tight')
plt.show()
Exercise 12.3
theta = np.linspace(0, 2*np.pi, 200)

set1 = (4, 1, np.pi/2)
set2 = (3.5, 1.5, np.pi/4)

f = lambda set: set[0] + set[1]*(np.sin(theta-set[2]))**2

fig = plt.figure(figsize=(10,4), dpi=100)

ax1 = fig.add_subplot(121)
ax1.plot(theta, f(set1), label="(a, b, c) = ({:.2f}, {:.2f}, {:.0f}$\degree$)".format(set1[0], set1[1], set1[2]/np.pi*180))
ax1.plot(theta, f(set2), label="(a, b, c) = ({:.2f}, {:.2f}, {:.0f}$\degree$)".format(set2[0], set2[1], set2[2]/np.pi*180))
ax1.set_xticks(np.linspace(0, 2*np.pi, 5))
ax1.grid(True)
ax1.set_title("Subplot 121")
ax1.set_xlabel(r"$\theta$", fontsize=15)
ax1.set_ylabel(r"$f$", fontsize=15)
ax1.legend()

ax2 = fig.add_subplot(122, projection='polar')
ax2.plot(theta, f(set1), label="(a, b, c) = ({:.2f}, {:.2f}, {:.0f}$\degree$)".format(set1[0], set1[1], set1[2]/np.pi*180))
ax2.plot(theta, f(set2), label="(a, b, c) = ({:.2f}, {:.2f}, {:.0f}$\degree$)".format(set2[0], set2[1], set2[2]/np.pi*180))
ax2.set_title("Subplot 122")
ax2.set_rticks(np.linspace(0,7,8))
ax2.set_rlabel_position(-90)
ax2.legend()

fig.savefig("exercise2.png", bbox_inches='tight', facecolor='white')

plt.show()
Exercise 12.4
freq = 440.0
period = 1 / freq

freq1 = freq/(2**(1/12))**9

t = np.linspace(0, 2*period, 1000)

c1 = np.sin(2*np.pi*freq*t)
c2 = np.sin(2*np.pi*freq1*t)

xticks = []
xticklabels = []
total_ticks = 9

for i in range(total_ticks):
    xticks.append(2*period/8*i)
    xticklabels.append("{:.2f}T".format(i/4))

fig, ax = plt.subplots(1, 1, figsize=(8, 3), dpi=100) 
ax.fill_between(t, y1=c1, y2=c2, where=None, color='green', alpha=0.1)
ax.plot(t, c1, label='A4')
ax.plot(t, c2, label='C4')
ax.set_title("Sinusoidal waves", fontweight='bold')
ax.set_ylabel("Amplitude", fontweight='bold')
ax.set_xlabel("# of Period", fontweight='bold')
ax.set_xlim([0, t.max()])
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels, fontweight='bold')
ax.set_yticks([-1., -0.5, 0., 0.5, 1.])
ax.set_yticklabels([-1., -0.5, 0., 0.5, 1.], fontweight='bold')
ax.legend()
ax.grid(True)
fig.savefig("exercise3.png", bbox_inches='tight', facecolor='white')
plt.show()