
thierryzhou
2023/02/22阅读:11主题:默认主题
Matplot 详解
简介
matplotlib 是 python 的一个绘图库,其取名来自 matrix + plot + library 三个单词的缩写。与 numpy、pandas 共享数据科学三剑客的美誉,也是很多高级可视化库的基础。matplotlib 不是 python 内置库,调用前需手动安装,且需依赖 numpy 库。
完整示例
### 使用 plot 函数绘图
import matplotlib.pyplot as plt
import numpy as np
plt.style.use('seaborn-whitegrid')
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))
plt.show()
# 使用 figure 和 ax
fig, ax = plt.subplots()
fig.suptitle('figure test')
ax.plot(x, np.sin(x), color='red', label='sin-function')
ax.legend(loc='upper right', frameon=True, shadow=True, framealpha=0.2)
plt.show()
模块
用 matplotlib 绘制可视化图表,主要有3种接口形式:
plt接口
最简单的绘图方式如下:
### 使用 plot 函数绘制折线
import matplotlib.pyplot as plt
import numpy as np
x = np.array([1,2])
y = np.array([1,2])
plt.plot(x, y)
plt.show()
用官方文档的原话,它是 matplotlib 的一个 state-based 交互接口,相关操作不面向特定的实例对象,而是面向"当前"图。
面向对象接口
最简单的面向对象绘图方式如下:
### 使用 plot 函数绘制折线
import matplotlib.pyplot as plt
import numpy as np
x = np.array([1,2])
y = np.array([1,2])
fig, ax = plt.subplots()
b = ax.plot(x, y)
plt.show()
这里的面向对象主要是指 Figure 和 Axes 两类对象。前文提到,Figure 提供了容纳多个 Axes 的画板,而 Axes 则是所有图标数据、图例配置等绘图形元素的容器。面向对象的绘图,就是通过调用 Figure 或 Axes 两类实例的方法完成绘图的过程(当然,Figure 和 Axes 发挥的作用是不同的)。通俗的说,就是将 matplotlib.plot 中的图形赋值给一个 Figure 或 Axes 实例,方便后续调用操作。
pylab接口
其引入了 numpy 和 pyplot 的所有接口,自然也可用于绘制图表,仍然可看做是 pyplot 接口形式。因其过于庞大官方不建议使用。
绘图方法
下面介绍一下,通过 Figure + Axes 绘图的方法。Figure 可以理解为一个画板容器,其容纳的内容包括画板本身的一些属性,标题(Title)以及一些 Axes 对象,我们常用的各种图表、图例、坐标轴等则都是 Axes 的内部元素。
为什么要将绘图接口封装在 matplotlib.pyplot 而不是 matplotlib 的顶级命名空间中呢?主要因为 matplotlib 还有另一个重要模块 pylab,pylab 被定位是 python 中对 MATLAB 的替代产品,也就是说凡是 MATLAB 可以实现的功能,pylab 通通都要有,例如矩阵运算(包括常规矩阵运算、线性代数、随机数、FFT等)、绘图功能等等。当了解 pylab 模块功能之后,才真正理解开发者的深谋远虑:原以为 matplotlib 的意思是"面向矩阵的绘图库",哪知其真正意义是"矩阵+绘图库",绘图只是它的一半。不过,也正因为 pylab 模块集成了过多的功能,直接调用并不是一个明智的选择,官方已不建议用其绘图。
鉴于 pylab 的特殊性,matplotlib 绘图主要采用前2种方式。而在二者之间:
-
如果是简单的单图表绘制,或者是交互实验环境,则plt接口足以满足需要,且操作简单易用 -
如果是多图表绘制,需要相对复杂的图例配置和其他自定义设置,那么毫无疑问面向对象接口绘图是当之无愧的不二选择
需要指出,Axes 从形式上是坐标轴 axis 一词的复数形式,但意义上却远非2个或多个坐标轴那么简单:如果将 Figure 比作是画板的话,那么 Axes 就是画板中的各个子图,这个子图提供了真正用于绘图的空间,除了包含纯粹的两个坐标轴(axes)外,自然还包括图形、图例等。所以准确的讲,如果说 Axes 和坐标轴有何关联的话,那么 Axes 应该算是广义的坐标轴,或简单称之为子图即可。
如何绘图

用 matplotlib 绘图一般也可以分3步:创建画板,绘制图表,配置图例。
1. 创建画板
包括创建 figure 和 axes 对象,常用有3种方法
1. plt.figure
主要接收一个元组作为 figsize 参数设置图形大小,返回一个 figure 对象用于提供画板。
2. plt.axes
接收一个 figure 或在当前画板上添加一个子图,返回该 axes 对象,并将其设置为"当前"图,缺省时会在绘图前自动添加。
3. plt.subplot
主要接收 3 个数字或 1 个 3 位数(自动解析成 3 个数字,要求解析后数值合理)作为子图的行数、列数和当前子图索引,索引从1开始(与 MATLAB 保存一致),返回一个 axes 对象用于绘图操作。
2. 绘制图表
figure 为绘图创建了画板,而 axes 基于当前画板创建了 1 个或多个子图对象。常用图表形式包括:
-
plot,折线图或点图,实际是调用了 line 模块下的 Line2D 图表接口。 -
scatter,散点图,常用于表述两组数据间的分布关系,也可由特殊形式下的 plot 实现。 -
bar/barh,条形图或柱状图,常用于表达一组离散数据的大小关系,比如一年内每个月的销售额数据;默认竖直条形图,可选 barh 绘制水平条形图。 -
hist,直方图,形式上与条形图很像,但表达意义却完全不同:直方图用于统计一组连续数据的分区间分布情况,比如有 1000 个正态分布的随机抽样,那么其直方图应该是大致满足钟型分布;条形图主要是适用于一组离散标签下的数量对比。 -
pie,饼图,主要用于表达构成或比例关系,一般适用于少量对比。 -
imshow,显示图像,根据像素点数据完成绘图并显示。
### 使用 plot
import matplotlib.pyplot as plt
import numpy as np
plt.style.use('seaborn-whitegrid')
##################################
## 折线图
xpoints = np.array([1, 2, 4, 8, 16, 32])
ypoints = np.array([1, 3, 5, 7, 9, 11])
fig, ax = plt.subplots()
ax.plot(xpoints, ypoints, marker = 'o')
plt.show()
##################################
## 柱状图
data = ((30, 1000), (10, 28), (100, 30),
(500, 800), (50, 10))
dim = len(data[0])
w = 0.6
dimw = w / dim
fig, ax = plt.subplots()
x = np.arange(len(data))
for i in range(len(data[0])):
y = [d[i] for d in data]
b = ax.bar(x + i * dimw, y,
dimw,
bottom = 0.001)
plt.show()
##################################
## 饼图
labels = 'Geek1', 'Geek2', 'Geek3', 'Geek4'
sizes = [10, 20, 30, 40]
explode = (0.1, 0, 0, 0)
fig1, ax1 = plt.subplots()
ax1.pie(sizes, explode = explode,
labels = labels, autopct ='% 1.1f %%',
shadow = True, startangle = 90)
plt.show()
3. 配置图例

matplotlib 常用属性如下:
-
title,设置图表标题。 -
axis / xlim / ylim,设置相应坐标轴范围,其中 axis 是对后 xlim 和 ylim 的集成,接受4个参数分别作为 x 和 y 轴的范围参数。 -
grid,添加图表网格线。 -
legend,在图表中添加label图例参数后,通过 legend 进行显示。 -
xlabel / ylabel,分别用于设置x、y轴标题。 -
xticks / yticks,分别用于自定义坐标轴刻度显示。 -
text / arrow / annotation,分别在图例指定位置添加文字、箭头和标记,一般很少用。
### 使用 plot
import matplotlib.pyplot as plt
import numpy as np
species = ("Adelie", "Chinstrap", "Gentoo")
penguin_means = {
'Bill Depth': (18.35, 18.43, 14.98),
'Bill Length': (38.79, 48.83, 47.50),
'Flipper Length': (189.95, 195.82, 217.19),
}
x = np.arange(len(species)) # the label locations
width = 0.25 # the width of the bars
multiplier = 0
fig, ax = plt.subplots(constrained_layout=True)
for attribute, measurement in penguin_means.items():
offset = width * multiplier
rects = ax.bar(x + offset, measurement, width, label=attribute)
ax.bar_label(rects, padding=3)
multiplier += 1
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_xlabel('Name')
ax.set_ylabel('Length (mm)')
ax.set_title('Penguin attributes by species')
ax.set_xticks(x + width, species)
ax.legend(loc='upper left', ncols=3)
ax.set_ylim(0, 250)
plt.show()
走向3D
在可视化愈发重要的当下,matplotlib当然不仅支持简单的2D图表绘制,其也提供了对3D绘图的丰富接口。
contour,实际上是一个伪3D图形,仍然是在2维空间绘图,但可以表达3维信息。例如在机器学习中,contour常用于绘制分类算法的超平面
如果需要绘制真3D图形,则需要额外导入matplotlib专用3D绘图库:mpl_toolkits,包括3D版的Axes对象和常用图表的3D版:
-
plot3D,3D版plot,可用于绘制3维空间的折线图或点图 -
scatter3D,3维散点图 -
bar3D,3维条形图 -
contour3D,3维等高线
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
colors = ['r', 'g', 'b', 'y']
yticks = [3, 2, 1, 0]
for c, k in zip(colors, yticks):
# Generate the random data for the y=k 'layer'.
xs = np.arange(20)
ys = np.random.rand(20)
# You can provide either a single color or an array with the same length as
# xs and ys. To demonstrate this, we color the first bar of each set cyan.
cs = [c] * len(xs)
cs[0] = 'c'
# Plot the bar graph given by xs and ys on the plane y=k with 80% opacity.
ax.bar(xs, ys, zs=k, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# On the y-axis let's only label the discrete values that we have data for.
ax.set_yticks(yticks)
plt.show()
更高级的封装
matplotlib 提供了大量丰富的可视化绘图接口,但仍然存在短板:例如绘图操作略显繁琐、图表不够美观。为此,在 matplotlib 基础上产生了一些封装更为便捷的可视化库,实现更为简单易用的接口和美观的图表形式,包括:
-
pandas.plot 一个最直接的对 matplotlib 绘图的封装,接口方法非常接近。 -
seaborn 是对 matplotlib 的高级封装,具有更为美观的图形样式和颜色配置,并提供了常用的统计图形接口,如 pairplot() 适用于表达多组数据间的关系。 -
ggplot 也是对 matplotlib 进行二次封装的可视化库,主要适用于 pandas 的 DataFrame 数据结构。
import pandas as pd
df = pd.DataFrame({
'name':['john','mary','peter','jeff','bill','lisa','jose'],
'age':[23,78,22,19,45,33,20],
'gender':['M','F','M','M','M','F','M'],
'state':['california','dc','california','dc','california','texas','texas'],
'num_children':[2,0,0,3,2,1,4],
'num_pets':[5,1,0,5,2,2,3]
})
df.plot(kind='line',x='num_children',y='num_pets',color='red')
plt.show()
df.plot(kind='bar',x='name',y='age')
plt.show()
更多技术分享浏览我的博客:
https://thierryzhou.github.io
参考
作者介绍

thierryzhou
关注云原生、云存储相关技术的程序员