Matplotlib 是 Python 中最基础、最常用的 数据可视化库,主要用于将数据绘制成各种图表,如折线图、柱状图、散点图、直方图、饼图等。它的主要模块是 matplotlib.pyplot
,用法类似 MATLAB,简单易用。
数据可视化的意义在于:
(1)帮助你“看见数据”的趋势、规律、异常值
(2)把复杂的数字变成易于理解的图像
(3)在报告、PPT、项目展示中更有说服力
(4)提高分析效率,便于数据解释和沟通
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [1, 4, 9, 16, 25]
plt.plot(x, y)
plt.title("平方数趋势图")
plt.xlabel("X 值")
plt.ylabel("Y = X^2")
plt.show()
输出图像: 一张简单的折线图展示了 x 与 y 的关系,远比你用眼去“数值对”看清晰得多!
(1)使用 pip 安装:
pip install matplotlib
(2)导入方式:
import matplotlib.pyplot as plt
参数解释:matplotlib
是库名;pyplot
是常用的绘图库模块;plt
是约定俗成的别名(方便写)
Matplotlib 图形的本质是:由一层层对象组成的可视化画布结构。
对象名 | 中文含义 | 作用 | 理解为 |
Figure | 整个图形窗口 | 包含所有图表的顶层容器 | 白纸/画布 |
Axes | 图表区域 | 实际绘图的区域(坐标系) | 一张子图 |
Axis | 坐标轴对象 | x轴和y轴的控制器 | 坐标刻度与范围 |
Artist | 艺术家对象 | 所有可见的元素(线、点、标题、标签等) | 真正画在纸上的内容 |
总结一句话:Figure 是总画布,Axes 是子图区域,Axis 是轴线控制,Artist 是画出来的东西。
我们用一个图来帮助你直观理解
+----------------------------------------------------+
| Figure |
| +--------------------------------------------+ |
| | Axes | |
| | +------------------------------------+ | |
| | | 坐标轴 (Axis) | | |
| | | 折线、 柱子、 点(Artist)| | |
| | +------------------------------------+ | |
| +--------------------------------------------+ |
+----------------------------------------------------+
一个 Figure
里可以放多个 Axes
,比如多子图(2x2,3x1 等排布)。
每个 Axes
里面再包含 Axis
(x轴/y轴)和 Artist
(线、图例、文字等)。
import matplotlib.pyplot as plt
fig = plt.figure() # 创建一个 Figure
ax = fig.add_subplot(1, 1, 1) # 创建一个 Axes(子图)
ax.plot([1, 2, 3], [4, 5, 6]) # 在 Axes 上绘图
plt.show()
fig
是整个画布;ax
是坐标区域;plot()
画出来的线、点是 Artist
Matplotlib 的绘图通常遵循以下 5 步标准流程:
① 准备数据 → ② 创建画布 → ③ 创建图表 → ④ 添加美化 → ⑤ 显示图像
import matplotlib.pyplot as plt
# 第1步:准备数据
x = [1, 2, 3, 4]
y = [10, 20, 25, 30]
# 第2步:创建画布
plt.figure(figsize=(6, 4)) # 可选设置图像大小
# 第3步:绘图
plt.plot(x, y, label='销售额', color='green', marker='o')
# 第4步:美化图形
plt.title("季度销售额")
plt.xlabel("季度")
plt.ylabel("金额(万元)")
plt.legend()
plt.grid(True)
# 第5步:显示图像
plt.show()
这五步流程基本适用于所有类型的图(折线图、柱状图、散点图等)。
plt.figure()
的作用(1)作用:plt.figure()
是创建一个新画布(即一个新的图像窗口)的函数。它一般在绘图开始时调用,相当于“开一张白纸”。
(2)常用参数:
参数 | 作用 |
figsize=(宽, 高) | 设置图像的大小(单位:英寸) |
dpi=100 | 图像分辨率,默认 100,越高越清晰 |
facecolor='white' | 设置背景色 |
注意:如果不写 plt.figure()
,Matplotlib 会自动创建一个默认画布;但在绘制多个图、保存图像时建议手动创建画布以避免混乱。
plt.show()
的使用时机作用:plt.show()
是显示图像的命令,用于把你画好的图真正显示出来(弹出窗口或 Jupyter 中呈现图像)。
场景 | 是否使用 |
Jupyter Notebook | 可选(一般自动显示) |
Python 脚本/IDE | 必须写 plt.show() 否则图不会显示 |
plt.plot([1, 2, 3], [4, 5, 6])
plt.show() # 现在图才会弹出显示
在写多个图时,每次 plt.show()
都会显示一个图,所以你可以控制每张图何时展示。
plt.savefig()
方法作用:将当前绘制好的图保存为图片文件(支持 PNG、JPG、SVG、PDF 等格式)。
常用语法:
plt.savefig("图名.png", dpi=300, bbox_inches='tight', transparent=True)
参数 | 作用 |
"图名.png" | 设置保存的文件名及格式 |
dpi=300 | 设置分辨率(打印建议300) |
bbox_inches='tight' | 自动剪除图像多余白边 |
transparent=True | 背景透明(适用于 PPT) |
plt.plot([1, 2, 3], [3, 5, 7])
plt.title("示例图")
plt.savefig("example_plot.png", dpi=300, bbox_inches='tight')
plt.show()
图像保存一般放在 plt.show()
之前 调用(否则可能保存为空图)。
作用:显示数据随 x 轴变化的趋势;适用于:时间序列、趋势分析
语法结构:
plt.plot(x, y, color='blue', linestyle='-', marker='o')
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [10, 15, 13, 18, 20]
plt.plot(x, y, label="销量趋势", color='green', marker='o')
plt.title("每月销售趋势图")
plt.xlabel("月份")
plt.ylabel("销售额(万元)")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.legend()
plt.grid(True)
plt.show()
作用:展示两个变量之间的关系(分布密度、聚类趋势);适用于:回归分析、聚类分析、异常检测
语法结构:
plt.scatter(x, y, s=点大小, c=颜色, alpha=透明度)
import numpy as np
x = np.random.rand(50)
y = np.random.rand(50)
colors = np.random.rand(50)
plt.scatter(x, y, c=colors, s=100, alpha=0.7)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.title("随机散点图")
plt.xlabel("x 值")
plt.ylabel("y 值")
plt.show()
作用:显示不同类别的数值比较;适用于:销售对比、分类统计、频率比较
#bar() 示例(垂直):
labels = ['A', 'B', 'C']
values = [10, 15, 7]
plt.bar(labels, values, color='skyblue')
plt.title("分类数据柱状图")
plt.xlabel("类别")
plt.ylabel("数量")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.show()
#barh() 示例(水平):
plt.barh(labels, values, color='orange')
plt.title("分类数据柱状图(水平)")
plt.xlabel("数量")
plt.ylabel("类别")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.show()
作用:显示连续型数据的分布(频数/频率);适用于:数据分布、偏态检验、离散程度分析
语法结构:
plt.hist(data, bins=组数, color='steelblue', edgecolor='black')
data = np.random.randn(1000) # 正态分布随机数
plt.hist(data, bins=30, color='purple', alpha=0.7)
plt.title("正态分布直方图")
plt.xlabel("值")
plt.ylabel("频数")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.show()
作用:表示各部分占整体比例(百分比);适用于:构成分析、占比展示
labels = ['苹果', '香蕉', '橙子', '梨子']
sizes = [40, 30, 20, 10]
colors = ['red', 'yellow', 'orange', 'green']
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
plt.axis('equal') # 让饼图为圆形
plt.title("水果市场份额")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.show()
作用:展示数据的分布、上下四分位、异常值;适用于:对比多个组的分布差异、发现异常值
data1 = np.random.normal(0, 1, 100)
data2 = np.random.normal(2, 1.5, 100)
plt.boxplot([data1, data2], labels=["组1", "组2"])
plt.title("两组数据的箱线图")
plt.ylabel("数值")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.show()
中位数:箱子中间的横线;异常值:箱子外的点;箱体:表示数据的中间 50%
作用:用于显示二维矩阵/图像的热度值或图片;适用于:图像处理、热度分析、矩阵可视化
matrix = np.random.rand(10, 10)
plt.imshow(matrix, cmap='hot', interpolation='nearest')
plt.colorbar() # 显示颜色条
plt.title("热图展示")
plt.show()
常用的 colormap 有:'hot'
:热度图;'cool'
:冷色图;'viridis'
:Matplotlib 默认;'gray'
:灰度图像
本章小结:
(1)设置图形标题:
plt.title("这是主标题", fontsize=16, color='darkblue', loc='center')
参数说明:fontsize:字体大小;color:标题颜色;loc:标题位置('center'
, 'left'
, 'right'
)
(2)设置坐标轴标签:
plt.xlabel("X轴标签", fontsize=12)
plt.ylabel("Y轴标签", fontsize=12)
(3)设置图例:
plt.plot([1, 2, 3], [2, 4, 1], label='数据A')
plt.legend(loc='upper left')
loc
常用位置值:'best'
(自动);'upper right'
, 'lower left';'center'
, 'center left'
等
(1)添加网格
plt.grid(True, linestyle='--', alpha=0.5)
参数:linestyle='--':虚线样式,alpha=0.5:透明度
(2)设置刻度值格式与方向:
plt.xticks([0, 1, 2], ['A', 'B', 'C'], rotation=45)
plt.yticks(fontsize=10)
xticks()
和 yticks()
可指定显示哪些位置的刻度,并改名称。
rotation
可以旋转文字角度。
折线图中常见设置:
plt.plot(x, y, color='red', linestyle='--', marker='o')
限定图像的显示区间:
plt.xlim(0, 10)
plt.ylim(5, 50)
适用于:裁剪图形、聚焦感兴趣的部分。
注意:也可以使用 ax.set_xlim()
和 ax.set_ylim()
在面向对象模式中设置。
(1)解决中文乱码(推荐方式):
plt.rcParams['font.family'] = 'SimHei' # 黑体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
'SimHei'
是黑体,适用于标题、标签等。
如果中文仍乱码,可安装中文字体或使用 matplotlib.font_manager 指定路径。
(2)更换字体样式(自定义):
from matplotlib import font_manager
font = font_manager.FontProperties(fname="你的字体路径.ttf")
plt.title("标题", fontproperties=font)
(1)创建图像时设置画布大小:
plt.figure(figsize=(8, 6), dpi=100)
参数 | 含义 |
figsize=(宽, 高) | 单位是英寸(1英寸=2.54厘米) |
dpi=100 | 每英寸像素数,决定清晰度 |
(2)多子图自动布局(避免重叠):
plt.tight_layout()
常配合 subplot
使用,避免图例、标题挤在一起。
import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [10, 20, 25, 30]
plt.figure(figsize=(6, 4), dpi=120)
plt.plot(x, y, color='green', linestyle='-', marker='o', label='增长趋势')
# 美化部分
plt.title("销售增长趋势图", fontsize=16)
plt.xlabel("季度", fontsize=12)
plt.ylabel("销售额(万元)", fontsize=12)
plt.legend(loc='upper left')
plt.grid(True, linestyle='--', alpha=0.5)
plt.xlim(0, 5)
plt.ylim(5, 35)
# 中文支持
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.tight_layout()
plt.show()
plt.subplot()
基本使用语法结构
plt.subplot(nrows, ncols, index)
参数说明:nrows
: 总行数;ncols
: 总列数;index
: 当前图的位置,从 1 开始编号,按行优先顺序排布。
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 4))
# 第1个子图
plt.subplot(2, 3, 1)
plt.title("图1")
plt.plot([1, 2, 3])
# 第2个子图
plt.subplot(2, 3, 2)
plt.title("图2")
plt.plot([3, 2, 1])
# ...
plt.tight_layout()
plt.show()
plt.subplots()
更灵活的子图方式基本用法:
fig, axes = plt.subplots(nrows, ncols)
返回一个 图像对象 fig
和 子图对象数组 axes
,可以更方便地访问和操作每个子图。
fig, axes = plt.subplots(2, 2, figsize=(8, 6))
axes[0, 0].plot([1, 2, 3])
axes[0, 0].set_title("子图 1")
axes[0, 1].plot([3, 2, 1])
axes[0, 1].set_title("子图 2")
axes[1, 0].bar([1, 2, 3], [3, 2, 5])
axes[1, 1].scatter([1, 2, 3], [3, 5, 2])
plt.tight_layout()
plt.show()
更加面向对象,适合复杂图形;axes
是二维数组(n×m),方便统一设置;可以统一设置 fig
的标题、保存图像等操作。
用法:
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
参数说明:sharex=True
:横轴共享;sharey=True
:纵轴共享;共享坐标轴后,可以方便比较图之间的差异。
import numpy as np
x = np.linspace(0, 10, 100)
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
for i in range(2):
for j in range(2):
axes[i, j].plot(x, np.sin(x + i + j))
axes[i, j].set_title(f"Subplot {i},{j}")
plt.tight_layout()
plt.show()
tight_layout()
自动优化排版如果你给每个子图加了标题或标签,默认排版可能会重叠,导致图不清晰。
plt.tight_layout()
自动调整子图之间的间距,避免重叠;
尤其适用于多个 subplot()
或 subplots()
的图。
fig, axes = plt.subplots(2, 2)
axes[0, 0].set_title("很长很长的标题")
plt.tight_layout()
plt.show()
#如果仍然排版不理想,可以传入参数微调:
plt.tight_layout(pad=1.5, h_pad=2.0, w_pad=2.0)
本章小节:
Pandas 提供了内置的 .plot()
方法(其实底层是 Matplotlib),可以非常方便地进行数据可视化。适用对象:Series.plot()/DataFrame.plot()
基本语法以及示例:
df.plot(kind='line') # 默认折线图
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data = pd.Series([1, 3, 2, 4])
data.plot(title="Series 绘图")
plt.show()
当 DataFrame
有多列时,调用 .plot()
会将每一列作为一条线画出来。
df = pd.DataFrame({
"A": np.random.randn(10),
"B": np.random.randn(10),
"C": np.random.randn(10)
})
df.plot(title="多列绘图(折线)")
plt.show()
#指定图类型:
df.plot(kind="bar") # 柱状图
df.plot(kind="area") # 面积图
df.plot(kind="box") # 箱线图
df.plot(kind="hist") # 直方图
df.plot(kind="kde") # 密度图(核密度估计)
#设置样式参数
df.plot(style='--o', alpha=0.7, figsize=(8, 5))
Pandas 的强大之处在于与分组统计联动绘图非常自然,可以用 groupby().plot()
或groupby().mean().plot()
等方式快速实现分组对比图。
示例 1:按类别分组后折线图
df = pd.DataFrame({
"category": ["A", "A", "B", "B", "C", "C"],
"value": [1, 3, 2, 5, 4, 6],
"year": [2020, 2021, 2020, 2021, 2020, 2021]
})
# 分组后平均值绘图
df.groupby("year").mean().plot(kind="bar")
plt.title("按年份平均值")
plt.show()
示例 2:分组后单独子图
for key, group in df.groupby("category"):
group.plot(x="year", y="value", label=key, title=f"分组:{key}")
plt.show()
Pandas 一行代码搞定:
df.groupby("year").mean().plot(kind="bar")
Matplotlib 原生写法则需要:
means = df.groupby("year").mean()
plt.bar(means.index, means["value"])
plt.show()
推荐做法:
日常数据分析、探索性数据分析(EDA):首选 Pandas 快速绘图;
精细控制图像排版、样式、子图组合:再使用 Matplotlib/Seaborn。
plt.savefig()
使用详解plt.savefig()
是 Matplotlib 中保存图像的核心方法。它将当前图像保存为文件,不会弹出显示窗口(除非调用了 plt.show()
)。
plt.savefig('filename.png')
示例:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
x = [1, 2, 3, 4, 5]
y = [3, 5, 2, 4, 6]
plt.figure(figsize=(6, 4))
plt.plot(x, y, marker='o', linestyle='--', color='b')
plt.title("示例图 - 高清透明")
plt.xlabel("X 轴")
plt.ylabel("Y 轴")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
plt.savefig("demo_transparent.svg", dpi=300, bbox_inches='tight', transparent=True)
plt.show()
一定要放在 plt.show()
前面,因为 show()
会清空图像。
保存路径可以是绝对路径或相对路径。
Matplotlib 会根据文件扩展名自动选择保存格式:
格式 | 特点 | 应用场景 |
.png | 无损压缩,常用 | 日常使用,报告 |
.jpg | 有损压缩,体积小 | 网页展示 |
.svg | 矢量图格式 | Web页面 |
矢量图,可打印 | 论文、打印、出版物 | |
.eps | 矢量图(老格式) | 出版印刷(较少使用) |
plt.plot([1, 2, 3], [4, 6, 5])
plt.title("格式示例")
# 保存为不同格式
plt.savefig("chart.png")
plt.savefig("chart.jpg")
plt.savefig("chart.pdf")
plt.savefig("chart.svg")
savefig()
可以设置以下常用参数来控制保存图像的质量和样式:
参数名 | 作用 | 示例 |
dpi | 图像分辨率 | dpi=300 |
bbox_inches | 图像边框设置,常用‘tight’去除空白边 | bbox_inches='tight' |
transparent | 背景透明 | transparent=True |
facecolor | 背景颜色(默认白色) | facecolor = ‘white’ |
pad_inches | 图像与边框的间距 | pad_inches = 0.1 |
plt.plot([1, 2, 3], [3, 2, 4])
plt.title("高质量输出")
plt.savefig(
"high_quality.png", # 文件名
dpi=300, # 高分辨率
bbox_inches='tight', # 去除空白边
transparent=True, # 背景透明
pad_inches=0.1 # 边距
)
本章小结:常用保存配置模板
需求 | 保存设置 |
报告图 | .png , dpi=200~300 , bbox_inches='tight' |
网页图 | .svg , transparent=True |
论文图 | .pdf , dpi=300+ , bbox_inches='tight' |
背景透明 | transparent=True , 可选 facecolor='none' |