Matplotlib#

Matplotlib是Python的二维绘图库,用于生成符合出版质量或跨平台交互环境的各类图形。

准备数据#

一维数据#

import numpy as np
x = np.linspace(0, 10, 100)
y = np.cos(x)
z = np.sin(x)

二维数据或图片#

data = 2 * np.random.random((10, 10))
data2 = 3 * np.random.random((10, 10))
Y, X = np.mgrid[-3:3:100j, -3:3:100j]
U = -1 - X**2 + Y
V = 1 + X - Y**2

绘制图形#

导入库#

import matplotlib.pyplot as plt
%matplotlib inline
Matplotlib is building the font cache; this may take a moment.
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[10], line 1
----> 1 import matplotlib.pyplot as plt
      2 get_ipython().run_line_magic('matplotlib', 'inline')

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/pyplot.py:57
     55 from cycler import cycler  # noqa: F401
     56 import matplotlib
---> 57 import matplotlib.image
     58 from matplotlib import _api
     59 # Re-exported (import x as x) for typing.

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/image.py:25
     23 import matplotlib.artist as martist
     24 import matplotlib.colorizer as mcolorizer
---> 25 from matplotlib.backend_bases import FigureCanvasBase
     26 import matplotlib.colors as mcolors
     27 from matplotlib.transforms import (
     28     Affine2D, BboxBase, Bbox, BboxTransform, BboxTransformTo,
     29     IdentityTransform, TransformedBbox)

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/backend_bases.py:49
     46 import numpy as np
     48 import matplotlib as mpl
---> 49 from matplotlib import (
     50     _api, backend_tools as tools, cbook, colors, _docstring, text,
     51     _tight_bbox, transforms, widgets, is_interactive, rcParams)
     52 from matplotlib._pylab_helpers import Gcf
     53 from matplotlib.backend_managers import ToolManager

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/text.py:16
     14 from . import _api, artist, cbook, _docstring
     15 from .artist import Artist
---> 16 from .font_manager import FontProperties
     17 from .patches import FancyArrowPatch, FancyBboxPatch, Rectangle
     18 from .textpath import TextPath, TextToPath  # noqa # Logically located here

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/font_manager.py:1643
   1639     _log.info("generated new fontManager")
   1640     return fm
-> 1643 fontManager = _load_fontmanager()
   1644 findfont = fontManager.findfont
   1645 get_font_names = fontManager.get_font_names

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/font_manager.py:1637, in _load_fontmanager(try_read_cache)
   1635             _log.debug("Using fontManager instance from %s", fm_path)
   1636             return fm
-> 1637 fm = FontManager()
   1638 json_dump(fm, fm_path)
   1639 _log.info("generated new fontManager")

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/font_manager.py:1103, in FontManager.__init__(self, size, weight)
   1100 for path in [*findSystemFonts(paths, fontext=fontext),
   1101              *findSystemFonts(fontext=fontext)]:
   1102     try:
-> 1103         self.addfont(path)
   1104     except OSError as exc:
   1105         _log.info("Failed to open font file %s: %s", path, exc)

File ~/checkouts/readthedocs.org/user_builds/getstarted/envs/latest/lib/python3.12/site-packages/matplotlib/font_manager.py:1136, in FontManager.addfont(self, path)
   1134     self.afmlist.append(prop)
   1135 else:
-> 1136     font = ft2font.FT2Font(path)
   1137     prop = ttfFontProperty(font)
   1138     self.ttflist.append(prop)

KeyboardInterrupt: 

画布#

fig = plt.figure()
<Figure size 640x480 with 0 Axes>
fig2 = plt.figure(figsize=plt.figaspect(2.0))
<Figure size 400x800 with 0 Axes>

坐标轴#

图形是以坐标轴为核心绘制的,大多数情况下,子图就可以满足需求。子图是栅格系统的坐标轴。

ax1 = fig.add_subplot(221)  # row-col-num
ax3 = fig.add_subplot(212)
fig3, axes = plt.subplots(nrows=2, ncols=2)
../_images/620832415d21997013ab0249e5c9c2bf138f3adc7cb7a94cb4cdaeb7c03599a4.png
fig4, axes2 = plt.subplots(ncols=3)
../_images/a0d0bedb9ae636febab8a043b0bab2ae9ff764212008279ee5f897d8ecf0e74c.png
fig.add_axes(ax1)
<Axes: >

绘图例程#

一维数据#

fig, ax = plt.subplots()
../_images/aeac237892ef1dfaa033a631eb05185635373fd22431899b2b275d89c648871a.png
lines = ax.plot(x, y)  # 用线或标记连接点
ax.scatter(x, y)  # 缩放或着色未连接的点
<matplotlib.collections.PathCollection at 0x1f5851f3b80>
axes[0, 0].bar([1, 2, 3], [3, 4, 5])  # 绘制柱状图
<BarContainer object of 3 artists>
axes[1, 0].barh([0.5, 1, 2.5], [0, 1, 2])  # 绘制水平柱状图
<BarContainer object of 3 artists>
axes[1, 1].axhline(0.45)  # 绘制与轴平行的横线
<matplotlib.lines.Line2D at 0x1f58555a040>
axes[0, 1].axvline(0.65)  # 绘制与轴垂直的竖线
<matplotlib.lines.Line2D at 0x1f585dbd640>
ax.fill(x, y, color="blue")  # 绘制填充多边形
[<matplotlib.patches.Polygon at 0x1f585dbdca0>]
ax.fill_between(x, y, color="yellow")  # 填充 y 值和 0 之间
<matplotlib.collections.PolyCollection at 0x1f585dc61c0>

向量场#

axes[0, 1].arrow(0, 0, 0.5, 0.5)  # 为坐标轴添加箭头
<matplotlib.patches.FancyArrow at 0x1f585dc6520>
axes[1, 1].quiver(y, z)  # 二维箭头
<matplotlib.quiver.Quiver at 0x1f585dc6760>
axes[0, 1].streamplot(X, Y, U, V)  # 二维箭头
<matplotlib.streamplot.StreamplotSet at 0x1f58555a220>

数据分布#

ax1.hist(y)  # 直方图
(array([26.,  8.,  7.,  6.,  6.,  6.,  6.,  7.,  8., 20.]),
 array([-9.99947166e-01, -7.99952450e-01, -5.99957733e-01, -3.99963016e-01,
        -1.99968300e-01,  2.64169119e-05,  2.00021134e-01,  4.00015850e-01,
         6.00010567e-01,  8.00005283e-01,  1.00000000e+00]),
 <BarContainer object of 10 artists>)
ax3.boxplot(y)  # 箱形图
{'whiskers': [<matplotlib.lines.Line2D at 0x1f5855b16d0>,
  <matplotlib.lines.Line2D at 0x1f5855c14c0>],
 'caps': [<matplotlib.lines.Line2D at 0x1f5855c1d90>,
  <matplotlib.lines.Line2D at 0x1f585627580>],
 'boxes': [<matplotlib.lines.Line2D at 0x1f5855b1520>],
 'medians': [<matplotlib.lines.Line2D at 0x1f585627e80>],
 'fliers': [<matplotlib.lines.Line2D at 0x1f58564d310>],
 'means': []}
ax3.violinplot(z)  # 小提琴图
{'bodies': [<matplotlib.collections.PolyCollection at 0x1f58564c550>],
 'cmaxes': <matplotlib.collections.LineCollection at 0x1f58564ddc0>,
 'cmins': <matplotlib.collections.LineCollection at 0x1f585886670>,
 'cbars': <matplotlib.collections.LineCollection at 0x1f585894700>}

二维数据或图片#

fig, ax = plt.subplots()
../_images/aeac237892ef1dfaa033a631eb05185635373fd22431899b2b275d89c648871a.png
axes2[0].pcolor(data2)  # 二维数组伪彩色图
<matplotlib.collections.PolyCollection at 0x1f58587a4c0>
axes2[0].pcolormesh(data)  # 二维数组等高线伪彩色图
<matplotlib.collections.QuadMesh at 0x1f583c46af0>
CS = plt.contour(Y, X, U)  # 等高线图
../_images/63db202414697da084ac55eaabeb381fc92e2e802529247c5825ef2c027b0964.png
axes2[2] = ax.clabel(CS)  # 等高线图标签

图形解析与工作流#

图形解析#

工作流#

Matplotlib 绘图的基本步骤:

  • Step 1 准备数据

  • Step 2 创建图形

  • Step 3 绘图

  • Step 4 自定义设置

  • Step 5 保存图形

  • Step 6 显示图形

import matplotlib.pyplot as plt
x = [1, 2, 3, 4]  # Step 1
y = [10, 20, 25, 30]
fig = plt.figure()  # Step 2
<Figure size 640x480 with 0 Axes>
ax = fig.add_subplot(111)  # Step 3
ax.plot(x, y, color="lightblue", linewidth=3)  # Step 3, 4
[<matplotlib.lines.Line2D at 0x1f584d73190>]
ax.scatter([2, 4, 6], [5, 15, 25], color="darkgreen", marker="^")
<matplotlib.collections.PathCollection at 0x1f584d73370>
ax.set_xlim(1, 6.5)
(1.0, 6.5)
plt.savefig("../_tmp/plt_savefig.png")  # Step 5
<Figure size 640x480 with 0 Axes>
plt.show()  # Step 6

自定义图形#

颜色、色条与色彩表#

plt.plot(x, x, x, [i**2 for i in x], x, [i**3 for i in x])
[<matplotlib.lines.Line2D at 0x1f584df7700>,
 <matplotlib.lines.Line2D at 0x1f584df7760>,
 <matplotlib.lines.Line2D at 0x1f584df7790>]
../_images/9f14bf4f17fc2848ab8d676019cf0967192ee9f7b44267f6652c6d524941967f.png
ax.plot(x, y, alpha=0.4)
[<matplotlib.lines.Line2D at 0x1f584e2cf70>]
ax.plot(x, y, c="k")
[<matplotlib.lines.Line2D at 0x1f584d80a90>]

标记#

fig, ax = plt.subplots()
../_images/aeac237892ef1dfaa033a631eb05185635373fd22431899b2b275d89c648871a.png
ax.scatter(x, y, marker=".")
<matplotlib.collections.PathCollection at 0x1f584d80df0>
ax.plot(x, y, marker="o")
[<matplotlib.lines.Line2D at 0x1f584eaed00>]

线型#

plt.plot(x, y, linewidth=4.0)
[<matplotlib.lines.Line2D at 0x1f5861a7310>]
../_images/ffa54f50cfdf0697a630a6e773dc34a6625b18ec2efdfd1ba95f7181670a2a98.png
plt.plot(x, y, ls="solid")
[<matplotlib.lines.Line2D at 0x1f586230490>]
../_images/625bf1b70f45b39da39abc319e6b92a0eff444b370ee9dd1492648b423a59b67.png
plt.plot(x, y, ls="--")
[<matplotlib.lines.Line2D at 0x1f5862b9160>]
../_images/6273ff25d0b588f051c86a53efab7a2b9834163770128876af49b20e9c62b3c5.png
plt.plot(x, y, "--", [i**2 for i in x], [i**2 for i in y], "-.")
[<matplotlib.lines.Line2D at 0x1f586338f40>,
 <matplotlib.lines.Line2D at 0x1f5863460a0>]
../_images/db41827c0c32a5c09bcc5289635273c541f9947aec2825fb8f6caa828a9d2f11.png
plt.setp(lines, color="r", linewidth=4.0)
[None, None]

文本与标注#

ax.text(1, -2.1, "Example Graph", style="italic")
Text(1, -2.1, 'Example Graph')
ax.annotate(
    "Sine",
    xy=(8, 0),
    xycoords="data",
    xytext=(10.5, 0),
    textcoords="data",
    arrowprops=dict(arrowstyle="->", connectionstyle="arc3"),
)
Text(10.5, 0, 'Sine')

数学符号#

plt.title(r"$sigma_i=15$", fontsize=20)
Text(0.5, 1.0, '$sigma_i=15$')
../_images/b503b28826e61e9ddc85b7ddfc40d17ca2b9ed40cc03c2ff24104df05f2364ba.png

尺寸限制、图例和布局#

尺寸限制与自动调整

ax.margins(x=0.0, y=0.1)  # 添加内边距
ax.axis("equal")  # 将图形纵横比设置为 1
(1.0, 4.0, 8.0, 32.0)
ax.set(xlim=[0, 10.5], ylim=[-1.5, 1.5])  # 设置 x 轴与 y 轴的限制
[(0.0, 10.5), (-1.5, 1.5)]
ax.set_xlim(0, 10.5)  # 设置 x 轴的限制
(0.0, 10.5)

图例

ax.set(title="An Example Axes", ylabel="Y-Axis", xlabel="X-Axis")  # 设置标题与 x、y 轴的标签
[Text(0.5, 1.0, 'An Example Axes'),
 Text(4.444444444444445, 0.5, 'Y-Axis'),
 Text(0.5, 4.444444444444445, 'X-Axis')]
ax.legend(loc="best")  # 自动选择最佳的图例位置
No artists with labels found to put in legend.  Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
<matplotlib.legend.Legend at 0x1f5875bf610>

标记

ax.xaxis.set(ticks=range(1, 5), ticklabels=[3, 100, -12, "foo"])  # 手动设置 X 轴刻度
[[<matplotlib.axis.XTick at 0x1f584e5b520>,
  <matplotlib.axis.XTick at 0x1f584e5b4f0>,
  <matplotlib.axis.XTick at 0x1f584e2ceb0>,
  <matplotlib.axis.XTick at 0x1f584e8a8b0>],
 [Text(1, 0, '3'), Text(2, 0, '100'), Text(3, 0, '-12'), Text(4, 0, 'foo')]]
ax.tick_params(axis="y", direction="inout", length=10)  # 设置 Y 轴长度与方向

子图间距

fig3.subplots_adjust(
    wspace=0.5, hspace=0.3, left=0.125, right=0.9, top=0.9, bottom=0.1
)  # 调整子图间距
fig.tight_layout()  # 设置画布的子图布局

坐标轴边线

ax1.spines["top"].set_visible(False)  # 隐藏顶部坐标轴线
ax1.spines["bottom"].set_position(("outward", 10))  # 设置底部边线的位置为 outward

保存#

savefig函数

plt.savefig("../_tmp/plt_savefig.png")  # 保存画布
<Figure size 640x480 with 0 Axes>
plt.savefig("../_tmp/plt_savefig_transparent.png", transparent=True)  # 保存透明画布
<Figure size 640x480 with 0 Axes>

显示图形#

show函数

plt.show()

关闭与清除#

绘图清除与关闭

plt.cla()  # 清除坐标轴
../_images/aeac237892ef1dfaa033a631eb05185635373fd22431899b2b275d89c648871a.png
plt.clf()  # 清除画布
<Figure size 640x480 with 0 Axes>
plt.close()  # 关闭窗口