5

Python 可视化模块 Matplotlib 的使用

 1 year ago
source link: https://xujinzh.github.io/2023/04/12/python-matplotlib-useage/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Python 可视化模块 Matplotlib 的使用

发表于2023-04-12|更新于2023-04-17|technologypython
字数总计:2.3k|阅读时长:10分钟|阅读量:9

Matplotlib 是 Python 中的数据可视化软件包,支持跨平台。Jonh D. Hunter 于 2002 年开始编写,2003 年发布第一版,并加入 BSD 开源软件组织。Matplotlib 提供了面向绘图对象的 API,能够实现常用图像的绘制,并能配合 Python GUI 工具(如 PyQt, Tkinter 等)把图像嵌入到应用程序中,同时也支持以脚本形式嵌入 IPython Shell, Jupyter notebook, Web 应用服务器中使用.

Matplotlib 架构和图像构成

Matplotlib 架构由 3 个层次构成,分别是:

  1. 后端层。作为最底层,它包含 3 个基类,分别是 FigureCanvas(图层画布,提供绘图的画布)、Renderer(绘图操作,提供画布上绘图的方法)、Event(事件处理,处理鼠标、键盘事件);
  2. 美工层。提供绘图的标题、坐标刻度、轴标签;
  3. 脚本层。负责生成图像和坐标系。

Matplotlib 图像由 4 个层次构成,分别是:

  1. Figure:画布,包含所有元素,如标题、轴线等;
  2. Axes:绘图区,或轴域区;
  3. Axis:坐标轴,包含轴长、轴标签和刻度等;
  4. Artist:文本对象(title, label)等能看到的所有对象。

Matplotlib 安装与使用

# 安装最新版
pip install matplotlib
# 安装指定的版本
pip install matplotlib==3.2.2
# 卸载
pip uninstall matplotlib

面向对象绘图

Python 是一门面向对象的语言,Matplotlib 也提供了对象类,如画布类、绘图区类等,下面根据类实例化方法画一个图。

import matplotlib.pyplot as plt  # 常用画图类 matplotlib.pyplot
import numpy as np # numpy 是 Python 中科学计算的基础包。提供多维数组对象,各种派生对象(如掩码数组和矩阵)等等

x = np.linspace(-5, 5, 101)
y = np.cos(x)

fig = plt.figure(figsize=(3, 3), dpi=100) # 创建画布实例,并设置画布大小和显示DPI
ax = fig.add_axes(
rect=[0, 0, 1, 1]
) # 创建绘图区类或轴域类,并指定绘图区域 rect,从左向右分别表示距离画布左、下的距离,绘图区域的宽和高,都是相对画布的比例值,取值都在 [0, 1]
ax.set_title("余弦曲线") # 设置标题
ax.set_xlabel("弧度") # 设置横轴标签
ax.set_ylabel("余弦值") # 设置纵轴标签
ax.plot(
x, y, color="cyan", marker="o", linestyle="dashed", linewidth=1, markersize=6
) # 画曲线
plt.show() # 显示图像

png

上面的面向对象绘图根据常规绘图的步骤进行,先创建画布,然后创建绘图区,最后绘图。有时,为了快速绘图,我们可以直接一条命令绘图,它会自动创建画布和绘图区。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-5, 5, 101)
y = np.cos(x)
plt.plot(
x, y, color="purple", marker="^", linestyle="dashed", linewidth=1, markersize=6
) # 自动创建合适大小的画布和绘图区进行绘图
plt.title("余弦曲线")
plt.xlabel("弧度")
plt.ylabel("余弦值")
plt.show()

png
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-5, 5, 101)
plt.plot(
x,
np.cos(x),
color="purple",
marker="^",
linestyle="dashed",
linewidth=1,
markersize=6,
label="余弦",
)
plt.plot(x, np.sin(x), "go", label="正弦") # color 和 marker 简写。绘制第二条曲线
plt.title("正余弦曲线")
plt.xlabel("弧度")
plt.ylabel("正余弦值")
plt.legend()
plt.show()

png

Matplotlib subplot 绘多幅图-遮挡

有时我们想在一个画布上绘制多幅图,此时,可以使用 subplot 方法。但注意,subplot 会自动创建子图的画布,会覆盖、遮挡低层画布绘制的图像。

import matplotlib.pyplot as plt
import numpy as np

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

plt.subplot(1, 1, 1, facecolor="red") # 最低层画布
plt.plot(np.sin(x))

plt.subplot(
2, 2, 1, facecolor="cyan"
) # 中间层画布。注意该 2x2画布会覆盖上面整个画布,即使只画这一个图,其他区域也会被覆盖。注意与下面2x1的区别
plt.plot(np.sin(x))
plt.subplot(2, 2, 2, facecolor="red") # 中间层画布,
plt.plot(np.sin(x))
plt.subplot(2, 2, 3, facecolor="blue") # 中间层画布,
plt.plot(np.sin(x))
plt.subplot(2, 2, 4, facecolor="yellow") # 中间层画布,
plt.plot(np.sin(x))

# plt.subplot(2, 1, 1, facecolor='yellow')
# plt.plot(np.tan(x))
plt.subplot(2, 1, 2, facecolor="orange") # 最顶层画布。注意该画布只有下面一半的区域,因此不会覆盖上半区域
plt.plot(np.tan(x))

plt.show()

png

Matplotlib add_subplot 绘多幅图-堆叠

subplot 方法会用高层画布完全遮挡低层画布,包括低层画布的坐标刻度等信息。如果我们不想遮挡低层画布的未被高层画布覆盖的区域,可以使用 add_subplot 方法,它只遮挡绘图区,甚至低层画布的坐标轴刻度仍能保留下来。

import matplotlib.pyplot as plt
import numpy as np

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

fig = plt.figure()
ax1 = fig.add_subplot(111, facecolor="y") # 最低层画布颜色是黄色
ax1.plot(np.sin(x))
ax2 = fig.add_subplot(221, facecolor="c") # add_subplot 直接增加的是一个自带画布的绘图区(坐标轴)
ax2.plot(np.sin(x))
ax3 = fig.add_subplot(222, facecolor="b")
ax3.plot(np.cos(x))
ax4 = fig.add_subplot(212, facecolor="orange") # 最高层画布颜色是橙色
ax4.plot(np.tan(x))
plt.show()

png

并排画多张图

import matplotlib.pyplot as plt
import numpy as np

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

fig = plt.figure()
ax1 = fig.add_subplot(221, facecolor="y")
ax1.plot(np.sin(x))
ax2 = fig.add_subplot(222, facecolor="c")
ax2.plot(np.sin(x))
ax3 = fig.add_subplot(223, facecolor="b")
ax3.plot(np.cos(x))
ax4 = fig.add_subplot(224, facecolor="orange")
ax4.plot(np.tan(x))
plt.show()

png

Matplotlib add_axes 绘多幅图-堆叠在任意区域

add_axes 绘图类似于 add_subplot,但能画在低层画布的任何区域,灵活性更好

import matplotlib.pyplot as plt
import numpy as np

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

fig = plt.figure(facecolor="g")
ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8], facecolor="c")
ax2 = fig.add_axes([0.4, 0.35, 0.3, 0.3], facecolor="y")
ax1.plot(x, np.sin(x), "b")
ax2.plot(x, np.cos(x), "r")
ax1.set_title("正弦曲线")
ax2.set_title("余弦曲线")
ax2.text(0.5, 0.5, "我是余弦曲线的标识", transform=ax2.transAxes) # 绘制文本
plt.show()

png

取消坐标轴

import matplotlib.pyplot as plt
import numpy as np

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

fig = plt.figure(facecolor="g")
ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8], facecolor="c")
ax2 = fig.add_axes([0.4, 0.35, 0.3, 0.3], facecolor="y")
ax1.plot(x, np.sin(x), "b")
ax2.plot(x, np.cos(x), "r")
ax1.set_title("正弦曲线")
ax2.set_title("余弦曲线")
ax2.text(0.5, 0.5, "我是余弦曲线的标识", transform=ax2.transAxes)
ax2.axis("off") # 取消坐标轴
plt.show()

png

Matplotlib subplots 绘多幅图-均匀分布

使用 add_subplot 能够画多幅图,但如果索引指定不好,可能会造成绘图区覆盖情况。使用 subplots 能够很好地进行并排图像绘画。

import matplotlib.pyplot as plt
import numpy as np

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

fig, ax = plt.subplots(2, 2)
ax[0][0].plot(x, np.sin(x))
ax[0][0].set_title("正弦曲线")
ax[0][1].plot(x, np.cos(x))
ax[0][1].set_title("余弦曲线")
ax[1][0].plot(x, np.tan(x))
ax[1][0].set_title("正切曲线")
ax[1][1].plot(x, np.tanh(x))
ax[1][1].set_title("双曲正切曲线")
plt.show()

png

可以看到上图像的横坐标刻度和下图像的标题遮挡,可以使用如下的两种方法处理

import matplotlib.pyplot as plt
import numpy as np

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

fig, ax = plt.subplots(2, 2)
ax[0][0].plot(x, np.sin(x))
ax[0][0].set_title("正弦曲线")
ax[0][1].plot(x, np.cos(x))
ax[0][1].set_title("余弦曲线")
ax[1][0].plot(x, np.tan(x))
ax[1][0].set_title("正切曲线")
ax[1][1].plot(x, np.tanh(x))
ax[1][1].set_title("双曲正切曲线")
fig.tight_layout() # 自动调整
plt.show()

png
import matplotlib.pyplot as plt
import numpy as np

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

fig, ax = plt.subplots(2, 2)
ax[0][0].plot(x, np.sin(x))
ax[0][0].set_title("正弦曲线")
ax[0][1].plot(x, np.cos(x))
ax[0][1].set_title("余弦曲线")
ax[1][0].plot(x, np.tan(x))
ax[1][0].set_title("正切曲线")
ax[1][1].plot(x, np.tanh(x))
ax[1][1].set_title("双曲正切曲线")
plt.subplots_adjust(wspace=0.2, hspace=0.5) # 手动调整
plt.show()

png

Matplotlib subplot2grid 绘多幅图-不均匀划分

subplots 绘多幅图是均匀划分画布,如果想要不均匀划分,想把某些图占用更多的画布,可以采用 subplot2grid 方法

import matplotlib.pyplot as plt
import numpy as np

ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=2) # 画布不均匀划分
ax2 = plt.subplot2grid((3, 3), (0, 2), rowspan=3)
ax3 = plt.subplot2grid((3, 3), (1, 0), rowspan=2, colspan=2)

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

ax1.plot(x, np.sin(x))
ax1.set_title(r"$\sin$") # latex 数学公式
ax2.plot(x, np.cos(x))
ax2.set_title(r"$\cos$")
ax2.grid(color="r", ls="-.", lw=0.25) # 设置绘图区网格线
ax3.plot(x, np.tan(x))
ax3.set_title(r"$\tan$")
plt.tight_layout() # 自动调整子图间距
plt.show()

png
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits import mplot3d

fig = plt.figure()
# 创建绘图区域
ax = plt.axes(projection="3d")
# 构建xyz
z = np.linspace(0, 1, 100)
x = z * np.sin(20 * z)
y = z * np.cos(20 * z)
c = x + y
ax.scatter3D(x, y, z, c=c)
ax.set_title("3d Scatter plot")
plt.show()

png
  1. Matplotlib教程(非常详细)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK