Matplotlib是Python中最基础的可视化模块,主要用于绘制二维平面图。其它可视化库有些是基于matplotlib,例如:seaborn库就是基于matplotlib专用于统计数据可视化。
Matplotlib官网:Matplotlib — Visualization with Python
Matplotlib是第三方库,需要安装:pip install matplotlib
导入Matplotlib库:import matplotlib.pyplot as plt
基本概念
figure(画布),axes(坐标系),axis(坐标轴)
注:一个figure(画布),可以有一个axes也可以有多个axes,一个axes只能画一个图。
即一个画布,可以有一个图,也可以有多个子图。
创建Figure(figure对象)有两种方式
- 隐式创建Figure:绘制一个简单图时,例如 plt.xxx(...),系统会检测是否有Figure,若没有则自动创建一个Figure,并在该Figure上自动创建Axes(默认一个Figure一个Axes)。【缺陷:无法绘制多个图,无法设置画布】
- 显式创建Figure:plt.figure( ),创建一个空Figure。【适用:设置画布,绘制多个图】
plt.figure(num: 'int | str | Figure | SubFigure | None' = None, figsize: 'tuple[float, float] | None' = None, dpi: 'float | None' = None, *, facecolor: 'ColorType | None' = None, edgecolor: 'ColorType | None' = None, frameon: 'bool' = True, FigureClass: 'type[Figure]' = <class 'matplotlib.figure.Figure'>, clear: 'bool' = False, **kwargs) -> 'Figure'
参数:num编号或名称,figsize尺寸大小,dpi分辨率,facecolor背景色,edgecolor边界颜色,frameon是否显示边框,clear是否清除已存在的画布。
隐式创建Figure | plt.plot(...),plt.subplot(...)等 |
显式创建Figure | plt.figure( ) |
创建Axes(axes对象)的方式
- Figure.add_subplot(...):一次只能添加一个Axes。若在一个Figure添加多个Axes可多次添加。
- plt.subplot(...):结果同Figure.add_subplot(...)。plt.subplot(...)是Figure.add_subplot(...)的包装器(wrapper)。
- plt.subplots(...):没有参数nrows和ncols,则一个Figure上只有一个Axes。若有参数(nrows=m, ncols=n),则一个Figure上有m行n列的Axes。
- Figure.add_axes(...):指定一个Axes在Figure上的位置和大小,可以嵌套。
Figure.add_subplot(...) | 一次添加一个子图,可多次添加。返回Axes。 |
plt.subplot(...) | 一次添加一个子图,可多次添加。返回Axes。 |
plt.subplots(...) | 一次添加一个子图,也可以一次添加多个子图。 返回Figure和Axes(或Axes集合)。 |
Figure.add_axes(...) | 一次添加一个子图,指定位置和大小,可嵌套。返回Axes。 |
主要绘制图
一个子图:fig, ax = plt.subplots( )【ax为一个子图】
多个子图:fig, ax = plt.subplots(nrow, ncol)【ax[图索引] 为其中一个子图】
注:图索引:若所有子图都在一行,则图索引为第几列(索引号从0开始),例如:ax[0] 为第一个子图;若多行多列,则图索引为几行几列(索引号都从0开始),例如:ax[0,1] 为第一行第二列的子图。
函数(单个图) | 函数(一个子图) | 函数(多个子图中) | |
线图 | plt.plot(...) | ax.plot(...) | ax[图索引].plot(...) |
散点图 | plt.scatter(...) | ax.scatter(...) | ax[图索引].scatter(...) |
饼图 | plt.pie(...) | ax.pie(...) | ax[图索引].pie(...) |
直方图 | plt.hist(...) | ax.hist(...) | ax[图索引].hist(...) |
柱状图 | plt.bar(...) | ax.bar(...) | ax[图索引].bar(...) |
热图 | plt.imshow(...) | ax.imshow(...) | ax[图索引].imshow(...) |
箱线图 | plt.boxplot(...) | ax.boxplot(...) | ax[图索引].boxplot(...) |
图相关属性
函数(单个图) | 函数(一个子图) | 函数(多个子图中) | |
文本内容 | plt.text(...) | ax.text(...) | ax[图索引].text(...) |
网格线 | plt.grid(True) | ax.grid(True) | ax[图索引].grid(True) |
图例 | plt.legend(...) | ax.legend(...) | ax[图索引].legend(...) |
标题 | plt.title(...) | ax.set_title(...) | ax[图索引].set_title(...) |
x轴标签 | plt.xlabel(...) | ax.set_xlabel(...) | ax[图索引].set_xlabel(...) |
y轴标签 | plt.ylabel(...) | ax.set_ylabel(...) | ax[图索引].set_ylabel(...) |
x轴和y轴刻度 | plt.axis(...) | ax.axis(...) | ax[图索引].axis(...) |
x轴刻度(范围) | plt.xlim(...) | ax.set_xlim(...) | ax[图索引].set_xlim(...) |
y轴刻度(范围) | plt.ylim(...) | ax.set_ylim(...) | ax[图索引].set_ylim(...) |
x轴刻度(缩放) | plt.xscale(...) | ax.set_xscale(...) | ax[图索引].set_xscale(...) |
y轴刻度(缩放) | plt.yscale(...) | ax.set_yscale(...) | ax[图索引].set_yscale(...) |
x轴设置刻度位置 | plt.xticks(...) | ax.set_xticks(...) | ax[图索引].set_xticks(...) |
x轴设置刻度标签 | ax.set_xticklabels(...) | ax[图索引].set_xticklabels(...) | |
y轴设置刻度位置 | plt.yticks(...) | ax.set_yticks(...) | ax[图索引].set_yticks(...) |
y轴设置刻度标签 | ax.set_yticklabels(...) | ax[图索引].set_yticklabels(...) |
绘图步骤
- 导入matplotlib:import matplotlib.pyplot as plt
- 绘制图(单个图/一个子图,多个图,多个子图)
- 显示图:plt.show( )
帮助
matplotlib各函数/方法官方文档:API Reference — Matplotlib 3.9.2 documentation
matplotlib.pyplot各函数/方法官方文档:matplotlib.pyplot — Matplotlib 3.9.2 documentation
Figure各函数/方法官方文档:matplotlib.figure — Matplotlib 3.9.2 documentation
Axes各函数/方法官方文档:matplotlib.axes — Matplotlib 3.9.2 documentation
各函数说明文档:例如:① 导入库:import matplotlib.pyplot as plt,② help(plt.figure)
案例
1、显式创建Figure:
① 设置画布(尺寸大小,分辨率,背景色,边框颜色等)
import matplotlib.pyplot as plt
import numpy as np
data = np.random.randint(0,9,10)
# 创建figure(画布)并设置
fig = plt.figure(figsize=(3,2), dpi=200, layout='constrained', facecolor='lightskyblue')
fig.suptitle('Figure')
# 创建axes
ax = fig.add_subplot(111)
# 绘制图
ax.boxplot(data) # 箱线图
ax.set_title("box plot")
# 显示图
plt.show()
② 绘制多个图(多个画布)
import matplotlib.pyplot as plt
import numpy as np
data_1 = [np.random.randint(0,9,5),np.random.randint(10,19,5)]
data_2 = np.random.randint(0,16,10)
n = np.arange(10)
# 一个画布, 绘制一个热图
fig_1 = plt.figure()
ax1 = fig_1.add_subplot(111)
ax1.imshow(data_1)
ax1.set_title("heatmap plot")
# 一个画布, 绘制两个散点图
fig_2 = plt.figure(figsize=(5,3))
ax_1 = fig_2.add_subplot(1,2,1)
ax_1.plot(n,data_2,marker='o',linestyle='')
ax_1.set_title("scatter plot 1")
ax_1.text(1,2,"hello,scatter",fontsize=10)
ax_2 = fig_2.add_subplot(1,2,2)
ax_2.scatter(n,data_2)
ax_2.set_title("scatter plot 2")
plt.show()
2、隐式创建figure对象:
① 单个图(折线图)
import matplotlib.pyplot as plt
import numpy as np
n = np.arange(5)
data_1 = np.random.randint(0,9,5)
data_2 = np.random.randint(0,9,5)
plt.plot(n,data_1)
plt.plot(n,data_2)
plt.title("line plot")
plt.xlabel("num")
plt.ylabel("data")
plt.legend(['data_1','data_2'])
plt.grid(True)
plt.show()
简单的图,单个图和一个子图 没有太大差别。
一个子图(折线图)
import matplotlib.pyplot as plt
import numpy as np
n = np.arange(5)
data_1 = np.random.randint(0,9,5)
data_2 = np.random.randint(0,9,5)
fig, ax = plt.subplots()
ax.plot(n,data_1)
ax.plot(n,data_2)
ax.set_title("line plot (subplot)")
ax.set_xlabel("num")
ax.set_ylabel("data")
ax.legend(['data_1','data_2'])
ax.grid(True)
plt.show()
② 多个子图(柱状图,直方图-密度图,折线图,散点图)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
n = np.arange(5)
data1 = np.random.randint(0,20,5)
data2 = np.random.randn(20)
data3 = np.random.random(5)
color = np.random.rand(5)
fig, ax = plt.subplots(2,2,figsize=(8,8))
ax[0,0].bar(n,data1)
ax[0,0].set_title("bar plot")
ax[0,1].hist(data2,5,density=True, histtype='stepfilled', facecolor='g',alpha=0.75,label='直方图')
ax[0,1].set_title("hist plot")
pd.Series(data2).plot(kind='kde',label='密度图')
ax[1,0].pie(data1)
ax[1,0].set_title("pie plot")
s = ax[1,1].scatter(n,data3,c=color,cmap='viridis')
ax[1,1].set_title("scatter plot")
fig.colorbar(s)
plt.show()
补充:报错处理
1、安装超时问题
具体问题:若安装matplotlib(pip install matplotlib)时报错超时(Read timed out)。
解决方法:
尝试1、增加时间:pip install matplotlib --default-timeout=2000。
尝试2、使用国内镜像(例如:清华):pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple。
2、numpy版本和pandas、matplotlib版本匹配问题
matplotlib和pandas都依赖numpy,需注意版本匹配问题。
(2-1)若numpy与pandas版本不匹配,则导入pandas时报错:
ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
(2-2)若numpy与matplotlib版本不匹配,导入matplotlib时报错:
ImportError: Matplotlib requires numpy>=1.23; you have 1.22.0.
本次问题:已安装过pandas,安装matplotlib时自动卸载原来numpy并安装与matplotlib匹配的版本,而该版本numpy与pandas不匹配。)
本次错误处理过程:因numpy版本高于pandas所需版本,卸载原numpy,安装低版本numpy。结果该版本numpy低于matplotlib所需的版本。
最终处理方式:(使用国内镜像,将numpy、pandas、matplotlib都升级为最新版本)
- 升级numpy:pip install --upgrade numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
- 升级pandas:pip install --upgrade pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
- 升级matplotlib:目前已为最新版本,无需升级。
查看版本:
- 查看目前Python版本(cmd输入命令:python --version)。
- 查看目前pandas版本(python解释器:import pandas 和 pandas.__version_ 或者 cmd输入命令:pip show pandas)。
- 查看目前pandas版本以及依赖的版本(python解释器:import pandas 和 pandas.show_versions())
- 查看目前matplotlib版本(python解释器:import matplotlib 和 matplotlib.__version_ 或者 cmd输入命令:pip show matplotlib)
- 查看目前numpy版本(python解释器:import numpy 和 numpy.__version_)
3、密度图报错、安装scipy报错问题
具体问题:若使用pandas的plot 画密度图,需安装scipy库,否则报错:
ModuleNotFoundError: No module named 'scipy'
解决方法:cmd输入命令:pip install scipy
若安装scipy时报错:
ERROR: Could not find a version that satisfies the requirement scipy (from versions: none) ERROR: No matching distribution found for scipy
解决方法:(使用国内镜像安装)pip install scipy -i https://pypi.tuna.tsinghua.edu.cn/simple