- 官网 :
https://matplotlib.org/
1. Sample plots in Matplotlib
1.1 line plot
import matplotlib.pyplot as plt
import numpy as np
# Data for plotting
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, ax = plt.subplots()
ax.plot(t, s)
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='About as simple as it gets, folks')
ax.grid()
# fig.savefig("test.png")
plt.show()
![output_1_0.png](https://upload-images.jianshu.io/upload_images/25022251-577ccda038031f6d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.2 Multiple subplots in one figure
import numpy as np
import matplotlib.pyplot as plt
# 两张图一次生成
x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)
fig, (ax1, ax2) = plt.subplots(2, 1) # 生成多张图,单独设置详细数据
fig.suptitle('A tale of 2 subplots')
ax1.plot(x1, y1, 'o-')
ax1.set_ylabel('Damped oscillation')
ax2.plot(x2, y2, '.-')
ax2.set_xlabel('time (s)')
ax2.set_ylabel('Undamped')
plt.show()
![output_3_0.png](https://upload-images.jianshu.io/upload_images/25022251-7faeec6dce81dfbf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# 另外一种实现方式 单图数据做处理
x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)
plt.subplot(2, 1, 1)
plt.plot(x1, y1, 'o-')
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')
plt.subplot(2, 1, 2)
plt.plot(x2, y2, '.-')
plt.xlabel('time (s)')
plt.ylabel('Undamped')
# plt.show()
Text(0, 0.5, 'Undamped')
![output_4_1.png](https://upload-images.jianshu.io/upload_images/25022251-c2bde47e1d54027d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.3 Images
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
from matplotlib.path import Path
from matplotlib.patches import PathPatch
# Fixing random state for reproducibility
np.random.seed(19680801)
# First we'll generate a simple bivariate normal distribution.
delta = 0.025
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, ax = plt.subplots()
im = ax.imshow(Z, interpolation='bilinear', cmap=cm.RdYlGn,
origin='lower', extent=[-3, 3, -3, 3],
vmax=abs(Z).max(), vmin=-abs(Z).max())
plt.show()
![output_6_0.png](https://upload-images.jianshu.io/upload_images/25022251-a2536489eb121606.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# A sample image
with cbook.get_sample_data('grace_hopper.jpg') as image_file:
image = plt.imread(image_file)
fig, ax = plt.subplots()
ax.imshow(image)
ax.axis('off') # clear x-axis and y-axis
# And another image
# Data are 256x256 16-bit integers.
w, h = 256, 256
with cbook.get_sample_data('s1045.ima.gz') as datafile:
s = datafile.read()
A = np.frombuffer(s, np.uint16).astype(float).reshape((w, h))
fig, ax = plt.subplots()
extent = (0, 25, 0, 25)
im = ax.imshow(A, cmap=plt.cm.hot, origin='upper', extent=extent)
markers = [(15.9, 14.5), (16.8, 15)]
x, y = zip(*markers)
ax.plot(x, y, 'o')
ax.set_title('MRI')
plt.show()
A = np.random.rand(5, 5)
fig, axs = plt.subplots(1, 3, figsize=(10, 3))
for ax, interp in zip(axs, ['nearest', 'bilinear', 'bicubic']):
ax.imshow(A, interpolation=interp) # 最数据进行插值处理,三种插值方式
ax.set_title(interp.capitalize())
ax.grid(True)
plt.show()
![output_8_0.png](https://upload-images.jianshu.io/upload_images/25022251-ad6989796a065e12.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
x = np.arange(120).reshape((10, 12))
interp = 'bilinear'
fig, axs = plt.subplots(nrows=2, sharex=True, figsize=(3, 5))
axs[0].set_title('blue should be up')
axs[0].imshow(x, origin='upper', interpolation=interp)
axs[1].set_title('blue should be down')
axs[1].imshow(x, origin='lower', interpolation=interp)
plt.show()
![output_9_0.png](https://upload-images.jianshu.io/upload_images/25022251-d62c054645158510.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
delta = 0.025
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
path = Path([[0, 1], [1, 0], [0, -1], [-1, 0], [0, 1]])
patch = PathPatch(path, facecolor='none')
fig, ax = plt.subplots()
ax.add_patch(patch)
im = ax.imshow(Z, interpolation='bilinear', cmap=cm.gray,
origin='lower', extent=[-3, 3, -3, 3],
clip_path=patch, clip_on=True)
im.set_clip_path(patch)
plt.show()
![output_10_0.png](https://upload-images.jianshu.io/upload_images/25022251-ddba2016a196e54a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.4 Contouring and pseudocolor
import matplotlib.pyplot as plt
from matplotlib.colors import BoundaryNorm
from matplotlib.ticker import MaxNLocator
import numpy as np
# Basic pcolormesh
np.random.seed(19680801)
Z = np.random.rand(6, 10)
x = np.arange(-0.5, 10, 1) # len = 11
y = np.arange(4.5, 11, 1) # len = 7
fig, ax = plt.subplots()
ax.pcolormesh(x, y, Z)
<matplotlib.collections.QuadMesh at 0x1c7a3b0b1d0>
![output_12_1.png](https://upload-images.jianshu.io/upload_images/25022251-7b856ff295552e6f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# Non-rectilinear pcolormesh
x = np.arange(-0.5, 10, 1) # len = 11
y = np.arange(4.5, 11, 1) # len = 7
X, Y = np.meshgrid(x, y)
X = X + 0.2 * Y # tilt the coordinates.
Y = Y + 0.3 * X
fig, ax = plt.subplots()
ax.pcolormesh(X, Y, Z)
<matplotlib.collections.QuadMesh at 0x1c7a24a9198>
![output_13_1.png](https://upload-images.jianshu.io/upload_images/25022251-4fc309a83ccb50bc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# Centered Coordinates
x = np.arange(10) # len = 10
y = np.arange(6) # len = 6
X, Y = np.meshgrid(x, y)
fig, axs = plt.subplots(2, 1, sharex=True, sharey=True)
axs[0].pcolormesh(X, Y, Z, vmin=np.min(Z), vmax=np.max(Z), shading='auto')
axs[0].set_title("shading='auto' = 'nearest'")
axs[1].pcolormesh(X, Y, Z[:-1, :-1], vmin=np.min(Z), vmax=np.max(Z),
shading='flat')
axs[1].set_title("shading='flat'")
Text(0.5, 1.0, "shading='flat'")
![output_14_1.png](https://upload-images.jianshu.io/upload_images/25022251-c143891185b5afd9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# Making levels using Norms
# make these smaller to increase the resolution
dx, dy = 0.05, 0.05
# generate 2 2d grids for the x & y bounds
y, x = np.mgrid[slice(1, 5 + dy, dy),
slice(1, 5 + dx, dx)]
z = np.sin(x)**10 + np.cos(10 + y*x) * np.cos(x)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
levels = MaxNLocator(nbins=15).tick_values(z.min(), z.max())
# pick the desired colormap, sensible levels, and define a normalization
# instance which takes data values and translates those into levels.
cmap = plt.get_cmap('PiYG')
norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)
fig, (ax0, ax1) = plt.subplots(nrows=2)
im = ax0.pcolormesh(x, y, z, cmap=cmap, norm=norm)
fig.colorbar(im, ax=ax0)
ax0.set_title('pcolormesh with levels')
# contours are *point* based plots, so convert our bound into point
# centers
cf = ax1.contourf(x[:-1, :-1] + dx/2.,
y[:-1, :-1] + dy/2., z, levels=levels,
cmap=cmap)
fig.colorbar(cf, ax=ax1)
ax1.set_title('contourf with levels')
# adjust spacing between subplots so `ax1` title and `ax0` tick labels
# don't overlap
fig.tight_layout()
plt.show()
1.5 Histograms
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(19680801)
# example data
mu = 100 # mean of distribution
sigma = 15 # standard deviation of distribution
x = mu + sigma * np.random.randn(437)
num_bins = 50
fig, ax = plt.subplots()
# the histogram of the data
n, bins, patches = ax.hist(x, num_bins, density=True)
# add a 'best fit' line
y = ((1 / (np.sqrt(2 * np.pi) * sigma)) *
np.exp(-0.5 * (1 / sigma * (bins - mu))**2))
ax.plot(bins, y, '--')
ax.set_xlabel('Smarts')
ax.set_ylabel('Probability density')
ax.set_title(r'Histogram of IQ: $\mu=100$, $\sigma=15$')
# Tweak spacing to prevent clipping of ylabel
fig.tight_layout()
plt.show()
1.6 Paths
import matplotlib.path as mpath
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
Path = mpath.Path
path_data = [
(Path.MOVETO, (1.58, -2.57)),
(Path.CURVE4, (0.35, -1.1)),
(Path.CURVE4, (-1.75, 2.0)),
(Path.CURVE4, (0.375, 2.0)),
(Path.LINETO, (0.85, 1.15)),
(Path.CURVE4, (2.2, 3.2)),
(Path.CURVE4, (3, 0.05)),
(Path.CURVE4, (2.0, -0.5)),
(Path.CLOSEPOLY, (1.58, -2.57)),
]
codes, verts = zip(*path_data)
path = mpath.Path(verts, codes)
patch = mpatches.PathPatch(path, facecolor='r', alpha=0.5)
ax.add_patch(patch)
# plot control points and connecting lines
x, y = zip(*path.vertices)
line, = ax.plot(x, y, 'go-')
ax.grid()
ax.axis('equal')
plt.show()
![output_19_0.png](https://upload-images.jianshu.io/upload_images/25022251-648f56144b184dd1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.7 Three-dimensional plotting
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import numpy as np
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
# A StrMethodFormatter is used automatically
ax.zaxis.set_major_formatter('{x:.02f}')
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
![output_21_0.png](https://upload-images.jianshu.io/upload_images/25022251-cbc723f4f3cff1e0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.8 Streamplot
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
w = 3
Y, X = np.mgrid[-w:w:100j, -w:w:100j]
U = -1 - X**2 + Y
V = 1 + X - Y**2
speed = np.sqrt(U**2 + V**2)
fig = plt.figure(figsize=(7, 9))
gs = gridspec.GridSpec(nrows=3, ncols=2, height_ratios=[1, 1, 2])
# Varying density along a streamline
ax0 = fig.add_subplot(gs[0, 0])
ax0.streamplot(X, Y, U, V, density=[0.5, 1])
ax0.set_title('Varying Density')
# Varying color along a streamline
ax1 = fig.add_subplot(gs[0, 1])
strm = ax1.streamplot(X, Y, U, V, color=U, linewidth=2, cmap='autumn')
fig.colorbar(strm.lines)
ax1.set_title('Varying Color')
# Varying line width along a streamline
ax2 = fig.add_subplot(gs[1, 0])
lw = 5*speed / speed.max()
ax2.streamplot(X, Y, U, V, density=0.6, color='k', linewidth=lw)
ax2.set_title('Varying Line Width')
# Controlling the starting points of the streamlines
seed_points = np.array([[-2, -1, 0, 1, 2, -1], [-2, -1, 0, 1, 2, 2]])
ax3 = fig.add_subplot(gs[1, 1])
strm = ax3.streamplot(X, Y, U, V, color=U, linewidth=2,
cmap='autumn', start_points=seed_points.T)
fig.colorbar(strm.lines)
ax3.set_title('Controlling Starting Points')
# Displaying the starting points with blue symbols.
ax3.plot(seed_points[0], seed_points[1], 'bo')
ax3.set(xlim=(-w, w), ylim=(-w, w))
# Create a mask
mask = np.zeros(U.shape, dtype=bool)
mask[40:60, 40:60] = True
U[:20, :20] = np.nan
U = np.ma.array(U, mask=mask)
ax4 = fig.add_subplot(gs[2:, :])
ax4.streamplot(X, Y, U, V, color='r')
ax4.set_title('Streamplot with Masking')
ax4.imshow(~mask, extent=(-w, w, -w, w), alpha=0.5, cmap='gray', aspect='auto')
ax4.set_aspect('equal')
plt.tight_layout()
plt.show()
1.9 Ellipses
# Ellipse Demo
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Ellipse
# Fixing random state for reproducibility
np.random.seed(19680801)
NUM = 250
ells = [Ellipse(xy=np.random.rand(2) * 10,
width=np.random.rand(), height=np.random.rand(),
angle=np.random.rand() * 360)
for i in range(NUM)]
fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})
for e in ells:
ax.add_artist(e)
e.set_clip_box(ax.bbox)
e.set_alpha(np.random.rand())
e.set_facecolor(np.random.rand(3))
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
plt.show()
![output_25_0.png](https://upload-images.jianshu.io/upload_images/25022251-ee5ef589d4cfe3c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# Ellipse Rotated
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Ellipse
angle_step = 45 # degrees
angles = np.arange(0, 180, angle_step)
fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})
for angle in angles:
ellipse = Ellipse((0, 0), 4, 2, angle=angle, alpha=0.1)
ax.add_artist(ellipse)
ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)
plt.show()
2.0 Bar charts
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
from collections import namedtuple
np.random.seed(42)
Student = namedtuple('Student', ['name', 'grade', 'gender'])
Score = namedtuple('Score', ['score', 'percentile'])
# GLOBAL CONSTANTS
test_names = ['Pacer Test', 'Flexed Arm\n Hang', 'Mile Run', 'Agility',
'Push Ups']
test_units = dict(zip(test_names, ['laps', 'sec', 'min:sec', 'sec', '']))
def attach_ordinal(num):
"""Convert an integer to an ordinal string, e.g. 2 -> '2nd'."""
suffixes = {str(i): v
for i, v in enumerate(['th', 'st', 'nd', 'rd', 'th',
'th', 'th', 'th', 'th', 'th'])}
v = str(num)
# special case early teens
if v in {'11', '12', '13'}:
return v + 'th'
return v + suffixes[v[-1]]
def format_score(score, test):
"""
Create score labels for the right y-axis as the test name followed by the
measurement unit (if any), split over two lines.
"""
unit = test_units[test]
if unit:
return f'{score}\n{unit}'
else: # If no unit, don't include a newline, so that label stays centered.
return score
def format_ycursor(y):
y = int(y)
if y < 0 or y >= len(test_names):
return ''
else:
return test_names[y]
def plot_student_results(student, scores, cohort_size):
fig, ax1 = plt.subplots(figsize=(9, 7)) # Create the figure
fig.subplots_adjust(left=0.115, right=0.88)
fig.canvas.manager.set_window_title('Eldorado K-8 Fitness Chart')
pos = np.arange(len(test_names))
rects = ax1.barh(pos, [scores[k].percentile for k in test_names],
align='center',
height=0.5,
tick_label=test_names)
ax1.set_title(student.name)
ax1.set_xlim([0, 100])
ax1.xaxis.set_major_locator(MaxNLocator(11))
ax1.xaxis.grid(True, linestyle='--', which='major',
color='grey', alpha=.25)
# Plot a solid vertical gridline to highlight the median position
ax1.axvline(50, color='grey', alpha=0.25)
# Set the right-hand Y-axis ticks and labels
ax2 = ax1.twinx()
# Set the tick locations
ax2.set_yticks(pos)
# Set equal limits on both yaxis so that the ticks line up
ax2.set_ylim(ax1.get_ylim())
# Set the tick labels
ax2.set_yticklabels([format_score(scores[k].score, k) for k in test_names])
ax2.set_ylabel('Test Scores')
xlabel = ('Percentile Ranking Across {grade} Grade {gender}s\n'
'Cohort Size: {cohort_size}')
ax1.set_xlabel(xlabel.format(grade=attach_ordinal(student.grade),
gender=student.gender.title(),
cohort_size=cohort_size))
rect_labels = []
# Lastly, write in the ranking inside each bar to aid in interpretation
for rect in rects:
# Rectangle widths are already integer-valued but are floating
# type, so it helps to remove the trailing decimal point and 0 by
# converting width to int type
width = int(rect.get_width())
rank_str = attach_ordinal(width)
# The bars aren't wide enough to print the ranking inside
if width < 40:
# Shift the text to the right side of the right edge
xloc = 5
# Black against white background
clr = 'black'
align = 'left'
else:
# Shift the text to the left side of the right edge
xloc = -5
# White on magenta
clr = 'white'
align = 'right'
# Center the text vertically in the bar
yloc = rect.get_y() + rect.get_height() / 2
label = ax1.annotate(
rank_str, xy=(width, yloc), xytext=(xloc, 0),
textcoords="offset points",
horizontalalignment=align, verticalalignment='center',
color=clr, weight='bold', clip_on=True)
rect_labels.append(label)
# Make the interactive mouse over give the bar title
ax2.fmt_ydata = format_ycursor
# Return all of the artists created
return {'fig': fig,
'ax': ax1,
'ax_right': ax2,
'bars': rects,
'perc_labels': rect_labels}
student = Student('Johnny Doe', 2, 'boy')
scores = dict(zip(
test_names,
(Score(v, p) for v, p in
zip(['7', '48', '12:52', '17', '14'],
np.round(np.random.uniform(0, 100, len(test_names)), 0)))))
cohort_size = 62 # The number of other 2nd grade boys
arts = plot_student_results(student, scores, cohort_size)
plt.show()
2.1 Pie charts
import matplotlib.pyplot as plt
# Pie chart, where the slices will be ordered and plotted counter-clockwise:
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
fig1, ax1 = plt.subplots()
ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90)
ax1.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
plt.show()
![output_30_0.png](https://upload-images.jianshu.io/upload_images/25022251-a02576cc6d6cf200.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2.2 Tables
import numpy as np
import matplotlib.pyplot as plt
data = [[ 66386, 174296, 75131, 577908, 32015],
[ 58230, 381139, 78045, 99308, 160454],
[ 89135, 80552, 152558, 497981, 603535],
[ 78415, 81858, 150656, 193263, 69638],
[139361, 331509, 343164, 781380, 52269]]
columns = ('Freeze', 'Wind', 'Flood', 'Quake', 'Hail')
rows = ['%d year' % x for x in (100, 50, 20, 10, 5)]
values = np.arange(0, 2500, 500)
value_increment = 1000
# Get some pastel shades for the colors
colors = plt.cm.BuPu(np.linspace(0, 0.5, len(rows)))
n_rows = len(data)
index = np.arange(len(columns)) + 0.3
bar_width = 0.4
# Initialize the vertical-offset for the stacked bar chart.
y_offset = np.zeros(len(columns))
# Plot bars and create text labels for the table
cell_text = []
for row in range(n_rows):
plt.bar(index, data[row], bar_width, bottom=y_offset, color=colors[row])
y_offset = y_offset + data[row]
cell_text.append(['%1.1f' % (x / 1000.0) for x in y_offset])
# Reverse colors and text labels to display the last value at the top.
colors = colors[::-1]
cell_text.reverse()
# Add a table at the bottom of the axes
the_table = plt.table(cellText=cell_text,
rowLabels=rows,
rowColours=colors,
colLabels=columns,
loc='bottom')
# Adjust layout to make room for the table:
plt.subplots_adjust(left=0.2, bottom=0.2)
plt.ylabel("Loss in ${0}'s".format(value_increment))
plt.yticks(values * value_increment, ['%d' % val for val in values])
plt.xticks([])
plt.title('Loss by Disaster')
plt.show()
2.3 Scatter plots
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
# Load a numpy record array from yahoo csv data with fields date, open, close,
# volume, adj_close from the mpl-data/example directory. The record array
# stores the date as an np.datetime64 with a day unit ('D') in the date column.
price_data = (cbook.get_sample_data('goog.npz', np_load=True)['price_data']
.view(np.recarray))
price_data = price_data[-250:] # get the most recent 250 trading days
delta1 = np.diff(price_data.adj_close) / price_data.adj_close[:-1]
# Marker size in units of points^2
volume = (15 * price_data.volume[:-2] / price_data.volume[0])**2
close = 0.003 * price_data.close[:-2] / 0.003 * price_data.open[:-2]
fig, ax = plt.subplots()
ax.scatter(delta1[:-1], delta1[1:], c=close, s=volume, alpha=0.5)
ax.set_xlabel(r'$\Delta_i$', fontsize=15)
ax.set_ylabel(r'$\Delta_{i+1}$', fontsize=15)
ax.set_title('Volume and percent change')
ax.grid(True)
fig.tight_layout()
plt.show()
2.4 GUI widgets
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
# The parametrized function to be plotted
def f(t, amplitude, frequency):
return amplitude * np.sin(2 * np.pi * frequency * t)
t = np.linspace(0, 1, 1000)
# Define initial parameters
init_amplitude = 5
init_frequency = 3
# Create the figure and the line that we will manipulate
fig, ax = plt.subplots()
line, = plt.plot(t, f(t, init_amplitude, init_frequency), lw=2)
ax.set_xlabel('Time [s]')
axcolor = 'lightgoldenrodyellow'
ax.margins(x=0)
# adjust the main plot to make room for the sliders
plt.subplots_adjust(left=0.25, bottom=0.25)
# Make a horizontal slider to control the frequency.
axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
freq_slider = Slider(
ax=axfreq,
label='Frequency [Hz]',
valmin=0.1,
valmax=30,
valinit=init_frequency,
)
# Make a vertically oriented slider to control the amplitude
axamp = plt.axes([0.1, 0.25, 0.0225, 0.63], facecolor=axcolor)
amp_slider = Slider(
ax=axamp,
label="Amplitude",
valmin=0,
valmax=10,
valinit=init_amplitude,
orientation="vertical"
)
# The function to be called anytime a slider's value changes
def update(val):
line.set_ydata(f(t, amp_slider.val, freq_slider.val))
fig.canvas.draw_idle()
# register the update function with each slider
freq_slider.on_changed(update)
amp_slider.on_changed(update)
# Create a `matplotlib.widgets.Button` to reset the sliders to initial values.
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
def reset(event):
freq_slider.reset()
amp_slider.reset()
button.on_clicked(reset)
plt.show()
2.5 Filled curves
import numpy as np
import matplotlib.pyplot as plt
def koch_snowflake(order, scale=10):
"""
Return two lists x, y of point coordinates of the Koch snowflake.
Parameters
----------
order : int
The recursion depth.
scale : float
The extent of the snowflake (edge length of the base triangle).
"""
def _koch_snowflake_complex(order):
if order == 0:
# initial triangle
angles = np.array([0, 120, 240]) + 90
return scale / np.sqrt(3) * np.exp(np.deg2rad(angles) * 1j)
else:
ZR = 0.5 - 0.5j * np.sqrt(3) / 3
p1 = _koch_snowflake_complex(order - 1) # start points
p2 = np.roll(p1, shift=-1) # end points
dp = p2 - p1 # connection vectors
new_points = np.empty(len(p1) * 4, dtype=np.complex128)
new_points[::4] = p1
new_points[1::4] = p1 + dp / 3
new_points[2::4] = p1 + dp * ZR
new_points[3::4] = p1 + dp / 3 * 2
return new_points
points = _koch_snowflake_complex(order)
x, y = points.real, points.imag
return x, y
x, y = koch_snowflake(order=5)
plt.figure(figsize=(8, 8))
plt.axis('equal')
plt.fill(x, y)
plt.show()
2.6 Date handling
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.cbook as cbook
# Load a numpy structured array from yahoo csv data with fields date, open,
# close, volume, adj_close from the mpl-data/example directory. This array
# stores the date as an np.datetime64 with a day unit ('D') in the 'date'
# column.
data = cbook.get_sample_data('goog.npz', np_load=True)['price_data']
fig, ax = plt.subplots()
ax.plot('date', 'adj_close', data=data)
# Major ticks every 6 months.
fmt_half_year = mdates.MonthLocator(interval=6)
ax.xaxis.set_major_locator(fmt_half_year)
# Minor ticks every month.
fmt_month = mdates.MonthLocator()
ax.xaxis.set_minor_locator(fmt_month)
# Text in the x axis will be displayed in 'YYYY-mm' format.
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
# Round to nearest years.
datemin = np.datetime64(data['date'][0], 'Y')
datemax = np.datetime64(data['date'][-1], 'Y') + np.timedelta64(1, 'Y')
ax.set_xlim(datemin, datemax)
# Format the coords message box, i.e. the numbers displayed as the cursor moves
# across the axes within the interactive GUI.
ax.format_xdata = mdates.DateFormatter('%Y-%m')
ax.format_ydata = lambda x: f'${x:.2f}' # Format the price.
ax.grid(True)
# Rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them.
fig.autofmt_xdate()
plt.show()
2.7 Log plots
import numpy as np
import matplotlib.pyplot as plt
# Data for plotting
t = np.arange(0.01, 20.0, 0.01)
# Create figure
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)
# log y axis
ax1.semilogy(t, np.exp(-t / 5.0))
ax1.set(title='semilogy')
ax1.grid()
# log x axis
ax2.semilogx(t, np.sin(2 * np.pi * t))
ax2.set(title='semilogx')
ax2.grid()
# log x and y axis
ax3.loglog(t, 20 * np.exp(-t / 10.0))
ax3.set_xscale('log', base=2)
ax3.set(title='loglog base 2 on x')
ax3.grid()
# With errorbars: clip non-positive values
# Use new data for plotting
x = 10.0**np.linspace(0.0, 2.0, 20)
y = x**2.0
ax4.set_xscale("log", nonpositive='clip')
ax4.set_yscale("log", nonpositive='clip')
ax4.set(title='Errorbars go negative')
ax4.errorbar(x, y, xerr=0.1 * x, yerr=5.0 + 0.75 * y)
# ylim must be set after errorbar to allow errorbar to autoscale limits
ax4.set_ylim(bottom=0.1)
fig.tight_layout()
plt.show()
2.8 Polar plots
import numpy as np
import matplotlib.pyplot as plt
r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.plot(theta, r)
ax.set_rmax(2)
ax.set_rticks([0.5, 1, 1.5, 2]) # Less radial ticks
ax.set_rlabel_position(-22.5) # Move radial labels away from plotted line
ax.grid(True)
ax.set_title("A line plot on a polar axis", va='bottom')
plt.show()
2.9 Legends
import numpy as np
import matplotlib.pyplot as plt
# Make some fake data.
a = b = np.arange(0, 3, .02)
c = np.exp(a)
d = c[::-1]
# Create plots with pre-defined labels.
fig, ax = plt.subplots()
ax.plot(a, c, 'k--', label='Model length')
ax.plot(a, d, 'k:', label='Data length')
ax.plot(a, c + d, 'k', label='Total message length')
legend = ax.legend(loc='upper center', shadow=True, fontsize='x-large')
# Put a nicer background color on the legend.
legend.get_frame().set_facecolor('C0')
plt.show()