thierryzhou

V1

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(010100)

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种方式。而在二者之间:

  1. 如果是简单的单图表绘制,或者是交互实验环境,则plt接口足以满足需要,且操作简单易用
  2. 如果是多图表绘制,需要相对复杂的图例配置和其他自定义设置,那么毫无疑问面向对象接口绘图是当之无愧的不二选择

需要指出,Axes 从形式上是坐标轴 axis 一词的复数形式,但意义上却远非2个或多个坐标轴那么简单:如果将 Figure 比作是画板的话,那么 Axes 就是画板中的各个子图,这个子图提供了真正用于绘图的空间,除了包含纯粹的两个坐标轴(axes)外,自然还包括图形、图例等。所以准确的讲,如果说 Axes 和坐标轴有何关联的话,那么 Axes 应该算是广义的坐标轴,或简单称之为子图即可。

如何绘图

matplotlib
matplotlib

用 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 个或多个子图对象。常用图表形式包括:

  1. plot,折线图或点图,实际是调用了 line 模块下的 Line2D 图表接口。
  2. scatter,散点图,常用于表述两组数据间的分布关系,也可由特殊形式下的 plot 实现。
  3. bar/barh,条形图或柱状图,常用于表达一组离散数据的大小关系,比如一年内每个月的销售额数据;默认竖直条形图,可选 barh 绘制水平条形图。
  4. hist,直方图,形式上与条形图很像,但表达意义却完全不同:直方图用于统计一组连续数据的分区间分布情况,比如有 1000 个正态分布的随机抽样,那么其直方图应该是大致满足钟型分布;条形图主要是适用于一组离散标签下的数量对比。
  5. pie,饼图,主要用于表达构成或比例关系,一般适用于少量对比。
  6. imshow,显示图像,根据像素点数据完成绘图并显示。
### 使用 plot
import matplotlib.pyplot as plt
import numpy as np

plt.style.use('seaborn-whitegrid')

##################################
## 折线图
xpoints = np.array([12481632])
ypoints = np.array([1357911])

fig, ax = plt.subplots()

ax.plot(xpoints, ypoints, marker = 'o')
plt.show()

##################################
## 柱状图
data = ((301000), (1028), (10030),
        (500800), (5010))
  
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 = [10203040]
explode = (0.1000)
  
fig1, ax1 = plt.subplots()
ax1.pie(sizes, explode = explode,
        labels = labels, autopct ='% 1.1f %%',
        shadow = True, startangle = 90)
plt.show()

3. 配置图例

matplotlib
matplotlib

matplotlib 常用属性如下:

  1. title,设置图表标题。
  2. axis / xlim / ylim,设置相应坐标轴范围,其中 axis 是对后 xlim 和 ylim 的集成,接受4个参数分别作为 x 和 y 轴的范围参数。
  3. grid,添加图表网格线。
  4. legend,在图表中添加label图例参数后,通过 legend 进行显示。
  5. xlabel / ylabel,分别用于设置x、y轴标题。
  6. xticks / yticks,分别用于自定义坐标轴刻度显示。
  7. text / arrow / annotation,分别在图例指定位置添加文字、箭头和标记,一般很少用。
### 使用 plot
import matplotlib.pyplot as plt
import numpy as np

species = ("Adelie""Chinstrap""Gentoo")
penguin_means = {
    'Bill Depth': (18.3518.4314.98),
    'Bill Length': (38.7948.8347.50),
    'Flipper Length': (189.95195.82217.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(0250)

plt.show()

走向3D

在可视化愈发重要的当下,matplotlib当然不仅支持简单的2D图表绘制,其也提供了对3D绘图的丰富接口。

contour,实际上是一个伪3D图形,仍然是在2维空间绘图,但可以表达3维信息。例如在机器学习中,contour常用于绘制分类算法的超平面

如果需要绘制真3D图形,则需要额外导入matplotlib专用3D绘图库:mpl_toolkits,包括3D版的Axes对象和常用图表的3D版:

  1. plot3D,3D版plot,可用于绘制3维空间的折线图或点图
  2. scatter3D,3维散点图
  3. bar3D,3维条形图
  4. 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 = [3210]
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 基础上产生了一些封装更为便捷的可视化库,实现更为简单易用的接口和美观的图表形式,包括:

  1. pandas.plot 一个最直接的对 matplotlib 绘图的封装,接口方法非常接近。
  2. seaborn 是对 matplotlib 的高级封装,具有更为美观的图形样式和颜色配置,并提供了常用的统计图形接口,如 pairplot() 适用于表达多组数据间的关系。
  3. 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
V1

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