Python图表库Matplotlib 组成部分介绍(Good)

来自:

https://www.cnblogs.com/rustfisher/p/15042912.html

 

 Python图表库Matplotlib 组成部分介绍

图表有很多个组成部分,例如标题、x/y轴名称、大刻度小刻度、线条、数据点、注释说明等等。

我们来看官方给的图,图中标出了各个部分的英文名称(下图所示):

anatomy.png

 

v2-4c25a699041fade748cd2bb9bd0e45b5_1440w

 

图片展示了一个图表的结构解析,包含多个关键组成部分。图表顶部有标题“Anatomy of a figure”;右侧有图例(Legend),标注蓝色线为“Blue signal”,红色线为“Red signal”;图表区域有网格线(Grid);X轴和Y轴分别有轴标签(X axis label、Y axis label)、主刻度(Major tick)、主刻度标签(Major tick label)、次刻度(Minor tick)、次刻度标签(Minor tick label);蓝色线标注为“Line (line plot)”,红色线也属于线图,散点标记标注为“Markers (scatter plot)”;图表边缘有边框(Spines),整体构成一个完整的统计图表结构。 

 
该图表包含标题(Anatomy of a figure)、图例(Legend:Blue signal、Red signal)、网格(Grid)、X轴和Y轴(含轴标签、主刻度、主刻度标签、次刻度、次刻度标签)、线图(Line plot:蓝色线、红色线)、散点图标记(Markers (scatter plot))及边框(Spines)等组成部分。

 

Spine(英 [spaɪn]/美 [spaɪn])是英语名词,核心含义指“脊柱”或“脊髓”,复数形式为spines。

axes [英[ˈæksi:z]美[ˈækˌsiz]] axes的意思、解释 n.轴;斧头( ax的名词复数 );斧子( axe的名词复数 );(遭)解雇;倒闭;被停业;轴( axis的名词复数 );轴线;核心;对称中心线(将物体平分为二) v.(用斧)砍( axe的第三人称

legend 英[ˈledʒ(ə)nd] n.传说;传奇故事;(尤指某领域中的)传奇人物;解释 网络图例;联想;传奇机 复数:legends

 

Matplotlib提供了很多api,开发者可根据需求定制图表的样式。

绘图

先绘制一个示例图。然后以此为基础进行定制。

import matplotlib.pyplot as plt
import numpy as np
import math

x_list = []
y_list = []
for i in range(0, 365):
    x_list.append(i)
    y_list.append(math.sin(i * 0.1))
ax = plt.gca()
ax.set_title('matplotlib example')
ax.set_xlabel('x')
ax.set_ylabel('y = sin(x)')
ax.grid()
plt.plot(x_list, y_list)
plt.show()

 

这段代码的主要功能是使用matplotlib库绘制一个正弦曲线,具体解释如下:

1. 导入库

import matplotlib.pyplot as plt  # 用于绘图
import numpy as np               # 数值计算库(这里未实际使用,可能是预留)
import math                      # 用于数学计算(这里用其sin函数) 

2. 准备数据

x_list = []  # 存储x轴数据的列表
y_list = []  # 存储y轴数据的列表

# 循环生成365个数据点
for i in range(0, 365):
    x_list.append(i)               # x值为0到364的整数
    y_list.append(math.sin(i * 0.1))  # y值为sin(0.1*i),即对x进行缩放后的正弦值 
  • 这里通过循环生成了 365 组数据,x 从 0 到 364 递增,y 是 x 乘以 0.1 后的正弦值(相当于将 x 轴 “拉长”,使正弦曲线更平缓)。

3. 设置图表属性

plt.gca() 是 Matplotlib 中用于获取当前活跃的坐标轴对象(Axes)的函数,全称为 "Get Current Axes"。如果当前没有创建坐标轴,它会自动创建一个新的坐标轴并返回。
ax = plt.gca() # 获取当前图表的坐标轴对象 ax.set_title('matplotlib example') # 设置图表标题 ax.set_xlabel('x') # 设置x轴标签 ax.set_ylabel('y = sin(x)') # 设置y轴标签(注:实际y是sin(0.1x),标签描述略有简化) ax.grid() # 显示网格线
 

4. 绘图并显示

plt.plot(x_list, y_list)  # 绘制折线图,x为x_list,y为y_list
plt.show()                # 显示图表 

最终效果

运行代码后,会显示一个标题为 “matplotlib example” 的图表,x 轴为 0 到 364,y 轴为对应的正弦值,曲线呈现周期性波动(因 x 被 0.1 缩放,周期变为原来的 10 倍),且带有网格线,清晰展示了正弦函数的变化趋势。

 

运行得到

图片

 

红色框里的是 figure;绿色框里的叫做 ax。
代码中 ax = plt.gca() 获取到的就是绿色框框里的部分(对象)。

Figure 大图

Figure代表整张图,暂时称为“全图”或者“大图”。一张图里可以有多个子图表。最少必须要有一个图表。像上面那样。

Axes 数据图

图里显示着数据,暂称为“数据图”。一个大图里可以有多个数据图。但单个数据图对象只能在1个大图里。

多张数据图 subplots

例如同时存在2个数据图,如下图:
subplot1-2.png

import matplotlib.pyplot as plt
import numpy as np
import math

x_list = []
y_list = []
y2_list = []
for i in range(0, 365):
    x_list.append(i)
    y_list.append(math.sin(i * 0.1))
    y2_list.append(math.cos(i * 0.1))
fig, (ax1, ax2) = plt.subplots(2)
ax1.set_title('matplotlib-demo 1')
ax2.set_title('matplotlib-demo 2')
ax1.set_xlabel('x')
ax1.set_ylabel('y = sin(x)')
ax2.set_xlabel('x')
ax2.set_ylabel('y = cos(x)')
ax1.plot(x_list, y_list)
ax2.plot(x_list, y2_list)
plt.show()

 

调用subplots()接口,传入数字指定要多少张数据图。
返回的多张图要用括号括起来。每个数据图可以绘制(plot)不同的数据。
标题用set_title()来设置。

可以看到上下两张图太挤了,有重叠部分。可以在plt.show()之前加一个 fig.tight_layout() 让它们拉开一点距离。
subplot1-2-tight.png

坐标轴

对于2维数据图,它有2个坐标,横坐标和纵坐标。有一些接口可以设置参数。
例如控制坐标轴的名字 set_xlabel()  set_ylabel

显示数据范围

set_xlim 方法可以控制x轴数据显示范围。同理y轴用set_ylim来控制。
对于显示范围,set_xlim 方法主要参数为leftright;或者用 xmin和xmax。这两套不能同时使用。
set_ylim 主要参数是 top和bottom;或者 yminymax。这两套不能同时使用。

增加显示范围控制的代码

import matplotlib.pyplot as plt
import numpy as np
import math


x_list = []
y_list = []
y2_list = []
for i in range(0, 365):
    x_list.append(i)
    y_list.append(math.sin(i * 0.1))
    y2_list.append(math.cos(i * 0.1))
fig, (ax1, ax2) = plt.subplots(2)
ax1.set_title('matplotlib-demo 1')
ax1.set_xlabel('x')
ax1.set_ylabel('y = sin(x)')
ax2.set_title('matplotlib-demo 2')
ax2.set_xlabel('x')
ax2.set_ylabel('y = cos(x)')

ax1.set_xlim(left=50, right=200.6)  # 控制x轴显示范围
ax1.set_ylim(top=1, bottom=0.3)  # 控制y轴显示范围

ax2.set_xlim(xmin=1, xmax=156.6)  # 控制x轴显示范围
ax2.set_ylim(ymin=-0.3, ymax=0.3)  # 控制y轴显示范围

ax1.plot(x_list, y_list)
ax2.plot(x_list, y2_list)
fig.tight_layout()
plt.show()

 

运行结果
xylim.png

 

刻度

tick意思是标记。在坐标轴上的是刻度。Major tick暂称为大刻度,minor tick暂称为小刻度。
使用 set_xticks 方法控制刻度显示。传入的列表是我们希望显示的刻度。
minor 参数默认为False,不显示小刻度。

import matplotlib.pyplot as plt
import numpy as np
import math


x_list = []
y_list = []
y2_list = []
for i in range(0, 365):
    x_list.append(i)
    y_list.append(math.sin(i * 0.1))
    y2_list.append(math.cos(i * 0.1))
fig, (ax1, ax2) = plt.subplots(2)
ax1.set_title('matplotlib-demo 1')
ax1.set_xlabel('x')
ax1.set_ylabel('y = sin(x)')
ax2.set_title('matplotlib-demo 2')
ax2.set_xlabel('x')
ax2.set_ylabel('y = cos(x)')

ax1.set_xlim(left=50, right=200.6)  # 控制x轴显示范围
ax1.set_ylim(top=1, bottom=0.3)  # 控制y轴显示范围

ax2.set_xlim(xmin=1, xmax=156.6)  # 控制x轴显示范围
ax2.set_ylim(ymin=-0.3, ymax=0.3)  # 控制y轴显示范围

ax1.set_xticks([50, 60, 70, 150])
ax1.set_yticks([0.1, 0.2, 0.3, 0.7, 0.9])
ax1.grid()  # 显示格子

ax2.set_xticks([1, 60, 70, 150], minor=True)
ax2.set_yticks([-0.1, 0, 0.1, 0.3], minor=True)
ax2.grid()

ax1.plot(x_list, y_list)
ax2.plot(x_list, y2_list)
fig.tight_layout()
plt.show()

 

关键代码如下

ax1.set_xticks([50, 60, 70, 150])
ax1.set_yticks([0.1, 0.2, 0.3, 0.7, 0.9])
ax1.grid()  # 显示格子

ax2.set_xticks([1, 60, 70, 150], minor=True)
ax2.set_yticks([-0.1, 0, 0.1, 0.3], minor=True)
ax2.grid()

 

可见当minor=True,传入的刻度列表有可能不显示。

也可以控制大刻度上的文字旋转

    plt.setp(ax1.xaxis.get_majorticklabels(), rotation=-45)
    plt.setp(ax2.xaxis.get_majorticklabels(), rotation=-60)

import matplotlib.pyplot as plt
import numpy as np
import math


x_list = []
y_list = []
y2_list = []
for i in range(0, 365):
    x_list.append(i)
    y_list.append(math.sin(i * 0.1))
    y2_list.append(math.cos(i * 0.1))
fig, (ax1, ax2) = plt.subplots(2)
ax1.set_title('matplotlib-demo 1')
ax1.set_xlabel('x')
ax1.set_ylabel('y = sin(x)')
ax2.set_title('matplotlib-demo 2')
ax2.set_xlabel('x')
ax2.set_ylabel('y = cos(x)')

ax1.set_xlim(left=50, right=200.6)  # 控制x轴显示范围
ax1.set_ylim(top=1, bottom=0.3)  # 控制y轴显示范围

ax2.set_xlim(xmin=1, xmax=156.6)  # 控制x轴显示范围
ax2.set_ylim(ymin=-0.3, ymax=0.3)  # 控制y轴显示范围

ax1.set_xticks([50, 60, 70, 150])
ax1.set_yticks([0.1, 0.2, 0.3, 0.7, 0.9])
ax1.grid()  # 显示格子

ax2.set_xticks([1, 60, 70, 150], minor=True)
ax2.set_yticks([-0.1, 0, 0.1, 0.3], minor=True)
ax2.grid()

plt.setp(ax1.xaxis.get_majorticklabels(), rotation=-45)
plt.setp(ax2.xaxis.get_majorticklabels(), rotation=-60)

ax1.plot(x_list, y_list)
ax2.plot(x_list, y2_list)
fig.tight_layout()
plt.show()

 

 

边线 spine

spine 是脊柱的意思,这里我们先称为边线。有上下左右4条边线。名称是 top bottom left right
可以直接从图表对象获取它的边线,比如右边线 ax1.spines.right

一些简单的操作,例如

  • set_visible 显示和隐藏
  • set_ticks_position 刻度显示的位置
  • set_bounds 边线显示范围
  • set_linewidth 线的宽度

隐藏右边线和上边线

ax1.spines.right.set_visible(False)
ax1.spines.top.set_visible(False)

让刻度显示在右边和上方

ax2.yaxis.set_ticks_position('right')
ax2.xaxis.set_ticks_position('top')

设置边线显示范围

ax3.spines.left.set_bounds(-0.5, 0.5)
ax3.spines.top.set_bounds(340, 400)

设置线的宽度

ax3.spines.bottom.set_linewidth(2)

完整代码如下

import matplotlib.pyplot as plt
import numpy as np
import math 

x_list = []
y_list = []
for i in range(0, 365):
    x_list.append(i)
    y_list.append(math.sin(i * 0.1))

fig, (ax1, ax2, ax3) = plt.subplots(3)
ax_list = [ax1, ax2, ax3]
for i in range(0, 3):
    cur_ax = ax_list[i]
    cur_ax.set_title('matplotlib-demo.com ' + str(i))
    cur_ax.plot(x_list, y_list)
    cur_ax.set_xlabel('x')
    cur_ax.set_ylabel('y = sin(x)')

ax1.spines.right.set_visible(False)
ax1.spines.top.set_visible(False)

ax2.spines.bottom.set_visible(False)
ax2.spines.left.set_visible(False)
ax2.yaxis.set_ticks_position('right')
ax2.xaxis.set_ticks_position('top')

ax3.spines.left.set_bounds(-0.5, 0.5)
ax3.spines.top.set_bounds(340, 400)
ax3.spines.bottom.set_linewidth(2)

fig.tight_layout()
plt.show()

 

运行截图

 

数据点

控制数据点的样式。下面我们在一张图表里绘制多条数据线。

import matplotlib.pyplot as plt
import numpy as np
import math

x_list = []
y_list = []
y2_list = []
y3_list = []
for i in range(0, 20):
    x_list.append(i)
    y_list.append(math.sin(i) * 2 - 4)
    y2_list.append(math.sin(i) * 2)
    y3_list.append(math.cos(i) * 1.3 + 3)

plt.plot(x_list, y_list, color='blue', linestyle='-.', linewidth=2, markersize=4)
plt.plot(x_list, y2_list, 'go', linewidth=1)
plt.plot(x_list, y3_list, 'r+')
plt.show()

 

plot()方法中,支持多种选项。

linestyle支持的选项
'-', '--', '-.', ':', 'None', ' ', '', 'solid', 'dashed', 'dashdot', 'dotted'

 

注释 legend

添加注释,调用 lengend() 方法。

在前面代码基础上添加

    plt.plot(x_list, y_list, color='blue', linestyle='-.', linewidth=2, markersize=4)
    plt.plot(x_list, y2_list, 'go', linewidth=1)
    plt.plot(x_list, y3_list, 'r+')
    plt.legend(['math.sin(i) * 2 - 4', 'math.sin(i) * 2', 'math.cos(i) * 1.3 + 3'])

import matplotlib.pyplot as plt
import numpy as np
import math

x_list = []
y_list = []
y2_list = []
y3_list = []
for i in range(0, 20):
    x_list.append(i)
    y_list.append(math.sin(i) * 2 - 4)
    y2_list.append(math.sin(i) * 2)
    y3_list.append(math.cos(i) * 1.3 + 3)

plt.plot(x_list, y_list, color='blue', linestyle='-.', linewidth=2, markersize=4)
plt.plot(x_list, y2_list, 'go', linewidth=1)
plt.plot(x_list, y3_list, 'r+')
plt.legend(['math.sin(i) * 2 - 4', 'math.sin(i) * 2', 'math.cos(i) * 1.3 + 3'])
plt.show()

 

控制注释显示的地方,添加 bbox_to_anchor 和 bbox_transform 属性

plt.legend(['math.sin(i) * 2 - 4', 'math.sin(i) * 2', 'math.cos(i) * 1.3 + 3'], bbox_to_anchor=(1, 1),
               bbox_transform=plt.gcf().transFigure)

plt.gcf() 是一个常用函数,全称为 "Get Current Figure",作用是获取当前正在操作的图表(Figure 对象)。

在 Matplotlib 中,bbox_to_anchor 和 bbox_transform 是用于精细控制元素(如图例、文本、坐标轴等)位置的重要属性,通常配合 loc(位置参数)使用,用于准确定位元素在图表中的位置。

1. bbox_to_anchor(边界框锚点)

bbox_to_anchor 用于指定一个 “锚点框” 的位置,元素(如图例)的位置会基于这个锚点框来确定。它的值通常是一个元组 (x, y) 或 (x, y, width, height),表示锚点框的位置和大小(后两个参数可选,默认宽度和高度为 0,即一个点)。 
  • 核心作用:定义元素的参考基准点,元素的 loc(位置参数,如 'upper right''center' 等)会与这个锚点框的对应位置对齐。
  • 坐标体系:默认使用归一化坐标(即 (0,0) 表示左下角,(1,1) 表示右上角),但可通过 bbox_transform 改变坐标体系。

2. bbox_transform(边界框坐标变换)

bbox_transform 用于指定 bbox_to_anchor 所使用的坐标体系,默认值为 ax.transAxes(即当前坐标轴的归一化坐标)。通过修改它,可以让 bbox_to_anchor 基于其他坐标体系定位,例如: 
  • ax.transData:数据坐标(与 x 轴、y 轴的实际数值对应)。
  • fig.transFigure:整个图表的归一化坐标((0,0) 是图表左下角,(1,1) 是图表右上角)。
  • 核心作用:转换 bbox_to_anchor 的坐标含义,让锚点框可以基于不同的参考系(坐标轴、图表整体、数据等)定位。
import matplotlib.pyplot as plt
import numpy as np
import math

x_list = []
y_list = []
y2_list = []
y3_list = []
for i in range(0, 20):
    x_list.append(i)
    y_list.append(math.sin(i) * 2 - 4)
    y2_list.append(math.sin(i) * 2)
    y3_list.append(math.cos(i) * 1.3 + 3)

plt.plot(x_list, y_list, color='blue', linestyle='-.', linewidth=2, markersize=4)
plt.plot(x_list, y2_list, 'go', linewidth=1)
plt.plot(x_list, y3_list, 'r+')
plt.legend(['math.sin(i) * 2 - 4', 'math.sin(i) * 2', 'math.cos(i) * 1.3 + 3'], 
           bbox_to_anchor=(1, 1), bbox_transform=plt.gcf().transFigure)
plt.show()

 

中文乱码问题

在设置标题用到中文的时候,可能会出现乱码。
可以设置rcParams的字体,解决乱码问题。

plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']

至此,我们把图表中各个部分都简要介绍了一下。

 

posted @ 2025-10-26 18:00  emanlee  阅读(78)  评论(0)    收藏  举报