Python数据可视化实战:Matplotlib基础图表绘制指南(线图、柱状图、饼图、散点图与子图布局)
1. 从零开始:为什么你需要Matplotlib?
如果你刚开始学Python,或者刚接触数据分析,你可能会觉得数据可视化是个挺“玄乎”的东西。一堆枯燥的数字,怎么才能变成一眼就能看懂的图表呢?别担心,这正是Matplotlib要帮你解决的问题。我刚开始用的时候,也觉得它功能太多,参数复杂,有点无从下手。但用久了才发现,它就像一把瑞士军刀,基础功能其实非常直观,掌握了几个核心图表,你就能应付80%的日常需求了。
简单来说,Matplotlib是Python里最老牌、最核心的绘图库。它的设计哲学是“让简单的事情简单,让复杂的事情成为可能”。这意味着,你只需要两三行代码,就能画出一条线、几个柱子;而当你需要制作复杂的学术图表或者精美的报告插图时,它也能提供极其精细的控制。很多你后来会听说的高级可视化库,比如Seaborn,其实底层也是基于Matplotlib的。所以,学好Matplotlib,就等于打牢了数据可视化的地基。
那么,谁适合学这个指南呢?我总结了几类人:一是刚入门数据分析的“小白”,想快速把分析结果展示出来;二是学生或研究人员,需要为论文、报告绘制清晰的图表;三是任何需要经常和Excel图表“搏斗”,想用更自动、更灵活的方式生成图表的职场人。这篇指南不会讲太多深奥的理论,我会带你直接上手,用最实在的代码例子,把线图、柱状图、饼图、散点图这“四大金刚”以及如何把它们组合在一起(子图布局)讲清楚。我踩过的坑、总结的小技巧,都会揉在里面,保证你跟着做一遍就能画出像样的图。
2. 动手前的准备:环境与数据
在开始画图之前,我们得先把“画布”和“颜料”准备好。这个过程很简单,但一步都不能错。
2.1 安装与导入
首先,确保你的Python环境里已经安装了Matplotlib。如果你用的是Anaconda,那它通常已经自带了。如果不确定,打开你的命令行(终端或CMD),输入 pip install matplotlib 并回车,就能完成安装。我建议同时安装NumPy,因为生成示例数据时会经常用到它:pip install numpy。
安装好后,在Python脚本或Jupyter Notebook的开头,我们通过两行代码来引入它们:
import matplotlib.pyplot as plt
import numpy as np
这里有个约定俗成的习惯:matplotlib.pyplot 通常被简写为 plt,numpy 被简写为 np。几乎所有的教程和代码都这么写,所以我们也跟着来,这样你看别人的代码时也能无缝对接。
2.2 准备你的第一份数据
画图离不开数据。对于初学者,我们不用纠结数据从哪来,先用NumPy快速生成一些有规律的“假数据”来练手。这能让你专注于学习绘图函数本身,而不是数据清洗。
比如,我们可以生成一组从0到10的等差数列作为X轴,再生成它们的平方值作为Y轴:
x = np.linspace(0, 10, 20) # 在0到10之间生成20个等间隔的点
y = x ** 2 # 计算每个x的平方值
np.linspace 是一个非常实用的函数,它帮你生成指定范围内指定数量的均匀数值。你也可以用 np.arange,它类似于Python的 range,但支持小数步长。有了 x 和 y 这两组数据,我们就有了绘制一切图表的基础。在接下来的部分,我会反复用到类似的方法来构造数据,你可以慢慢体会不同数据适合用什么图表来呈现。
3. 趋势的描绘者:线图(Line Plot)
线图可能是你最常遇到的图表类型,它擅长展示数据随时间或其他连续变量的变化趋势。比如股票价格走势、每月销售额变化、温度随时间波动等等。
3.1 绘制最基本的直线与折线
我们用 plt.plot() 函数来画线图。它的基本用法简单到不可思议:plt.plot(x, y)。这里的 x 和 y 就是刚才我们准备的两个长度相同的列表或数组。
import matplotlib.pyplot as plt
import numpy as np
# 准备数据
x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]
# 绘制并显示
plt.plot(x, y)
plt.show()
运行这段代码,你会看到一个弹出窗口,里面画着一条从点(1,2)到点(5,10)的直线。这就是最简单的线图。但实际数据很少这么“乖”,它们通常是上下波动的。我们来画一个更真实的折线图:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [1, 4, 2, 3, 5, 2, 9, 5, 8, 6] # 一组随机波动的数据
plt.plot(x, y)
plt.show()
现在你看到的线就是一条有起伏的折线了。plt.plot() 函数默认会用直线段依次连接你提供的所有数据点。
3.2 让线图变得更专业:样式、标签与图例
如果只是画一条线,那和Excel没什么区别。Matplotlib的强大在于你可以精细地控制图表的每一个细节。我刚开始学的时候,最喜欢折腾的就是线的颜色、形状和标记点。
控制线条样式: plt.plot() 函数可以接受一个格式字符串参数,一次性定义颜色、标记点和线型。比如 'ro--' 表示红色(r)、圆圈标记(o)、虚线(--)。
x = np.linspace(0, 10, 20)
y = np.sin(x) # 生成正弦曲线
plt.plot(x, y, 'g*-', linewidth=2, markersize=8) # 绿色星形标记的实线,线宽2,标记大小8
plt.show()
常用的颜色代码有:b(蓝), g(绿), r(红), c(青), m(品红), y(黄), k(黑), w(白)。线型有:-(实线), --(虚线), :(点线), -.(点划线)。
添加图表标签: 一个没有标题和轴标签的图表是不完整的。用下面几个函数可以轻松加上:
plt.plot(x, y)
plt.title('正弦函数曲线') # 图表标题
plt.xlabel('X轴(角度)') # X轴标签
plt.ylabel('Y轴(sin值)') # Y轴标签
plt.grid(True, linestyle='--', alpha=0.5) # 添加网格线,虚线,半透明
plt.show()
绘制多条线与添加图例: 当你想在同一张图上比较多个数据序列时,就需要图例了。
x = np.linspace(0, 2*np.pi, 100)
y_sin = np.sin(x)
y_cos = np.cos(x)
plt.plot(x, y_sin, 'b-', label='sin(x)') # 用label参数指定这条线的名字
plt.plot(x, y_cos, 'r--', label='cos(x)')
plt.legend() # 显示图例
plt.title('正弦与余弦曲线对比')
plt.show()
plt.legend() 会自动根据每条线的 label 生成图例,并放在合适的位置。你也可以通过 loc 参数指定位置,比如 plt.legend(loc='upper right')。
4. 数量的比较者:柱状图与条形图(Bar Chart)
当我们需要比较不同类别的数值大小时,柱状图(Bar Chart)是最直观的选择。这里要注意一个中文语境下容易混淆的概念:通常我们说的“柱状图”是垂直的(bar),而水平的被称为“条形图”(barh)。它们本质上是一样的,只是方向不同。
4.1 绘制单组与多组柱状图
基础柱状图使用 plt.bar() 函数。你需要提供两个主要参数:每个柱子的位置(x)和每个柱子的高度(height)。
import matplotlib.pyplot as plt
# 数据:三个类别A, B, C的数值
categories = ['A', 'B', 'C']
values = [15, 24, 32]
plt.bar(categories, values, color='skyblue', edgecolor='black')
plt.title('单组柱状图示例')
plt.ylabel('数值')
plt.show()
color 参数控制柱子的填充色,edgecolor 控制边框颜色。你还可以用 width 参数调整柱子的宽度(默认0.8)。
绘制并列柱状图进行对比: 这是实际分析中非常常见的场景,比如比较同一产品在不同季度的销量。
import numpy as np
# 数据准备
labels = ['第一季度', '第二季度', '第三季度', '第四季度']
sales_2023 = [23, 45, 56, 78]
sales_2024 = [34, 52, 61, 85]
x = np.arange(len(labels)) # 生成类别的位置索引:[0, 1, 2, 3]
width = 0.35 # 柱子的宽度
# 绘制两组柱子,通过调整x位置实现并列
plt.bar(x - width/2, sales_2023, width, label='2023年', color='lightcoral')
plt.bar(x + width/2, sales_2024, width, label='2024年', color='lightseagreen')
plt.xlabel('季度')
plt.ylabel('销售额(万元)')
plt.title('年度销售额对比')
plt.xticks(x, labels) # 将x轴刻度位置设置为类别位置,标签用文字
plt.legend()
plt.show()
这里的关键技巧是:先创建一个数值型的x位置数组(np.arange(len(labels))),然后分别让两组柱子向左(x - width/2)和向右(x + width/2)偏移半个柱宽,从而实现并列。plt.xticks() 函数用于将底部的数字刻度替换成我们想要的文字标签。
4.2 绘制水平条形图
水平条形图用 plt.barh(),参数从 (x, height) 变成了 (y, width)。它特别适合类别名称较长的情况,因为横向布局有更多空间显示文字。
# 假设我们有一些需要长时间显示名称的类别
processes = ['数据收集与清洗', '特征工程处理', '模型训练阶段', '结果评估分析', '报告生成']
time_cost = [40, 25, 35, 20, 15] # 各阶段耗时(小时)
plt.barh(processes, time_cost, color='steelblue')
plt.xlabel('耗时(小时)')
plt.title('项目各阶段耗时分析')
plt.tight_layout() # 自动调整布局,防止标签被截断
plt.show()
plt.tight_layout() 是我强烈推荐的一个函数,它能自动调整子图参数,让标签、标题等元素不互相重叠,在图表元素较多时尤其有用。
5. 比例的展示者:饼图(Pie Chart)
饼图用于显示一个整体中各组成部分的比例关系。虽然数据可视化专家们经常批评饼图在精确比较上的不足(尤其是切片很多时),但在展示少数几个类别的占比时,它依然非常直观有效。
5.1 基础饼图与个性化设置
使用 plt.pie() 绘制饼图,核心参数是一个表示各部分大小的列表。
import matplotlib.pyplot as plt
# 数据:一天时间分配
activities = ['工作', '通勤', '用餐', '休息', '学习']
time = [9, 2, 2, 8, 3]
plt.pie(time, labels=activities, autopct='%1.1f%%')
plt.title('每日时间分配')
plt.show()
autopct 参数用于在饼图切片上显示百分比,'%1.1f%%' 表示格式化为一位小数的百分比。这是让饼图信息量倍增的关键设置。
让饼图更吸引人: 默认的饼图可能有点平淡,我们可以通过几个参数让它脱颖而出:
# 定义颜色和爆炸效果
colors = ['gold', 'lightcoral', 'lightskyblue', 'lightgreen', 'violet']
explode = (0.1, 0, 0, 0, 0) # 只“炸开”第一块(‘工作’)
plt.figure(figsize=(7, 7)) # 设置画布大小,让饼图更圆
plt.pie(time, labels=activities, autopct='%1.1f%%', startangle=90,
colors=colors, explode=explode, shadow=True)
plt.title('每日时间分配(突出工作部分)', fontsize=14)
plt.show()
这里引入了几个新参数:explode 是一个元组,指定每个切片离圆心的偏移距离,非零值就会产生“炸开”效果,用于强调某一部分。startangle 设置第一块切片的起始角度,90度表示从正上方开始。shadow=True 添加了一点阴影,让饼图有立体感。colors 列表让你可以自定义每一块的颜色。
5.2 饼图的实用技巧与注意事项
在实际使用饼图时,我有几个心得想分享。首先,切片数量不宜过多,最好控制在6块以内,否则会显得非常拥挤,难以辨认。如果类别太多,考虑把小的类别合并为“其他”。
其次,调整标签位置防止重叠。当某些切片很小时,其百分比标签可能会重叠或跑到饼图外面。labeldistance 和 pctdistance 参数可以分别调整类别文字和百分比数字离圆心的距离。
# 假设有一个部分特别小
sizes = [45, 30, 15, 8, 2]
labels = ['A', 'B', 'C', 'D', 'E']
plt.pie(sizes, labels=labels, autopct='%1.1f%%',
labeldistance=1.05, pctdistance=0.75)
plt.title('包含极小部分的饼图')
plt.show()
最后,虽然饼图很直观,但要记住它不适合比较细微的差异。比如,35%和40%的切片在饼图上看起来差别可能不大,但在柱状图上就一目了然。所以,选择图表类型时要始终考虑你的沟通目的。
6. 关系的探索者:散点图(Scatter Plot)
散点图是探索两个变量之间关系的利器。它不连接数据点,而是将每个数据点绘制在二维平面上,非常适合观察数据的分布模式、聚类情况或相关性。
6.1 基础散点图与样式自定义
使用 plt.scatter() 绘制散点图,最基本的调用方式也是 plt.scatter(x, y)。
import matplotlib.pyplot as plt
import numpy as np
# 生成一些随机数据点
np.random.seed(42) # 设置随机种子,确保每次运行生成相同的数据
x = np.random.rand(50) * 10 # 50个0-10之间的随机数
y = x * 2 + np.random.randn(50) * 2 # y大致是x的两倍,加上一些随机噪声
plt.scatter(x, y)
plt.xlabel('X变量')
plt.ylabel('Y变量')
plt.title('基础散点图')
plt.grid(True, alpha=0.3)
plt.show()
运行后你会看到一些随机分布的点,但隐约能看出它们沿着一条斜线分布。这就是散点图揭示相关性的能力。
自定义点的外观: scatter() 函数强大的地方在于,你可以非常灵活地控制每个点的颜色、大小和形状,甚至用颜色和大小来编码第三个、第四个变量。
# 生成更多数据,并添加第三个变量(点的大小)和第四个变量(点的颜色)
np.random.seed(123)
x = np.random.rand(100) * 100
y = np.random.rand(100) * 100
sizes = np.random.rand(100) * 500 # 点的大小,范围0-500
colors = np.random.rand(100) # 点的颜色值,范围0-1
plt.scatter(x, y, s=sizes, c=colors, alpha=0.6, cmap='viridis', edgecolors='black', linewidth=0.5)
plt.colorbar(label='颜色值') # 添加颜色条,解释颜色映射
plt.xlabel('X轴')
plt.ylabel('Y轴')
plt.title('用大小和颜色表示多维数据的散点图')
plt.show()
这里参数有点多,我解释一下:s 参数接受一个数组,为每个点指定不同的大小。c 参数接受一个数组,为每个点指定颜色值。cmap(颜色映射)指定如何将这些数值映射到具体的颜色('viridis' 是一种从黄到紫的渐变色)。alpha 控制透明度。edgecolors 和 linewidth 给每个点加上了黑色的细边框,让它们在背景上更清晰。plt.colorbar() 则添加了一个颜色标尺,告诉你什么颜色对应什么数值。
6.2 用散点图发现模式与异常值
散点图在数据探索阶段无比重要。我经常用它来快速检查数据质量。比如,你可以一眼看出是否存在明显的线性或非线性关系,数据点是否聚集成簇,以及是否存在远离群体的异常点。
# 模拟一份“年龄-收入”的数据,并加入一个异常值
ages = np.concatenate([np.random.normal(30, 5, 50), [65]]) # 50个正常年龄+1个65岁
incomes = np.concatenate([np.random.normal(50000, 10000, 50), [200000]]) # 对应收入,加一个高收入
plt.figure(figsize=(8, 6))
plt.scatter(ages[:-1], incomes[:-1], alpha=0.7, label='正常样本') # 先画正常点
plt.scatter(ages[-1], incomes[-1], color='red', s=150, edgecolors='black', label='异常值') # 再画异常点,突出显示
# 添加一些辅助分析线
plt.axhline(y=np.mean(incomes[:-1]), color='gray', linestyle='--', alpha=0.5, label='平均收入')
plt.axvline(x=np.mean(ages[:-1]), color='gray', linestyle=':', alpha=0.5, label='平均年龄')
plt.xlabel('年龄')
plt.ylabel('年收入(元)')
plt.title('年龄-收入散点图(检测异常值)')
plt.legend()
plt.show()
在这个例子里,我们用红色大圆点明确标出了一个可能的异常值(年龄较大但收入异常高)。plt.axhline() 和 plt.axvline() 分别添加了水平和垂直的参考线,标出了正常数据的平均收入线和平均年龄线,这有助于我们更直观地判断异常点偏离了多少。这种可视化能让你在正式分析前,就对数据的整体情况和潜在问题有一个清晰的把握。
7. 图表的交响乐:子图布局(Subplots)
单独一个图表往往不够用。在报告或仪表盘中,我们经常需要将多个相关的图表并排放在一起,方便对比和综合观察。这就是子图(Subplots)的用武之地。Matplotlib提供了几种灵活的方式来实现子图布局,刚开始可能觉得有点绕,但掌握后你会觉得无比自由。
7.1 使用plt.subplot()快速布局
plt.subplot() 是一种比较传统的子图创建方法,它按顺序在网格中激活一个子图区域。其基本语法是 plt.subplot(nrows, ncols, index),表示将画布分成 nrows 行 ncols 列,然后选择第 index 个位置(从左到右、从上到下编号,从1开始)作为当前绘图区。
import matplotlib.pyplot as plt
import numpy as np
# 准备一些数据
x = np.linspace(0, 10, 100)
plt.figure(figsize=(10, 6)) # 设置整个画布的大小
# 第一个子图:线图
plt.subplot(2, 2, 1) # 2行2列,第1个位置
plt.plot(x, np.sin(x), 'b-')
plt.title('正弦曲线')
plt.grid(True)
# 第二个子图:散点图
plt.subplot(2, 2, 2) # 2行2列,第2个位置
plt.scatter(x[:30], np.cos(x[:30]), c='r', alpha=0.6)
plt.title('余弦散点(前30点)')
# 第三个子图:柱状图
plt.subplot(2, 2, 3) # 2行2列,第3个位置
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 12]
plt.bar(categories, values, color='green', alpha=0.7)
plt.title('类别柱状图')
# 第四个子图:饼图
plt.subplot(2, 2, 4) # 2行2列,第4个位置
plt.pie([30, 25, 20, 25], labels=['部分1', '部分2', '部分3', '部分4'], autopct='%1.0f%%')
plt.title('占比饼图')
plt.tight_layout() # 再次强调,这个函数对于子图布局至关重要!
plt.show()
这种方法直观,但有个小缺点:每个子图的编号是全局的,如果你在中间想插入或删除一个子图,可能需要重新调整所有编号。它适合事先规划好布局的简单场景。
7.2 更强大的面向对象方式:fig, ax = plt.subplots()
这是我个人最推荐、也最常用的方法。它采用面向对象的风格,一次性创建所有子图,并返回一个图形对象(fig)和一个包含所有坐标轴对象的数组(ax)。这种方式代码更清晰,控制也更精细。
# 创建一个2行2列的子图网格,并返回图形对象和坐标轴对象数组
fig, axs = plt.subplots(2, 2, figsize=(10, 8)) # axs是一个2x2的数组
fig.suptitle('四种基础图表综合展示', fontsize=16) # 为整个图形添加总标题
# 现在,axs[0, 0] 代表第一行第一列的子图坐标轴,以此类推
x = np.linspace(0, 2*np.pi, 50)
# 左上角:带标记的线图
axs[0, 0].plot(x, np.sin(x), 'o-', markersize=4, label='sin(x)')
axs[0, 0].set_title('带标记的线图') # 注意这里用.set_title()而不是plt.title()
axs[0, 0].set_xlabel('X轴')
axs[0, 0].set_ylabel('Y轴')
axs[0, 0].legend()
axs[0, 0].grid(True, alpha=0.3)
# 右上角:随机散点图
np.random.seed(10)
scatter_x = np.random.rand(40)
scatter_y = np.random.rand(40)
colors = np.random.rand(40)
sizes = 100 * np.random.rand(40) ** 2
scatter = axs[0, 1].scatter(scatter_x, scatter_y, c=colors, s=sizes, alpha=0.7, cmap='plasma')
axs[0, 1].set_title('随机散点图(颜色与大小编码)')
fig.colorbar(scatter, ax=axs[0, 1]) # 将颜色条关联到特定的子图
# 左下角:分组柱状图
categories = ['G1', 'G2', 'G3', 'G4']
men_means = [20, 34, 30, 35]
women_means = [25, 32, 34, 20]
x_index = np.arange(len(categories))
width = 0.35
axs[1, 0].bar(x_index - width/2, men_means, width, label='男性', color='steelblue')
axs[1, 0].bar(x_index + width/2, women_means, width, label='女性', color='lightcoral')
axs[1, 0].set_title('分组柱状图对比')
axs[1, 0].set_xticks(x_index)
axs[1, 0].set_xticklabels(categories)
axs[1, 0].legend()
# 右下角:爆炸式饼图
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # 只炸开第二部分
axs[1, 1].pie(sizes, explode=explode, labels=['A', 'B', 'C', 'D'], autopct='%1.1f%%', shadow=True)
axs[1, 1].set_title('突出显示某部分的饼图')
# 调整整个图形中子图之间的间距
plt.subplots_adjust(wspace=0.3, hspace=0.4) # wspace控制水平间距,hspace控制垂直间距
plt.show()
这种方式的好处非常明显:每个子图都是一个独立的对象(axs[i, j]),你可以单独对它进行任何设置,而不会影响到其他子图。代码结构也更有条理,易于维护和扩展。fig.suptitle() 用于设置整个图形的总标题。fig.colorbar() 可以指定将颜色条关联到哪个具体的子图。plt.subplots_adjust() 则让你可以微调所有子图之间的间距。
7.3 复杂的不规则网格布局
有时候,你可能需要一个占据多行或多列的大图,旁边配上几个小图。这可以通过 plt.subplot2grid() 或更灵活的 gridspec 来实现。这里介绍一个相对简单的 subplot2grid 例子:
plt.figure(figsize=(12, 8))
# 定义一个3行3列的网格
# 第一个图占据第一行所有列(跨3列)
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
ax1.plot(np.random.randn(50).cumsum(), 'r-', linewidth=2) # 随机游走曲线
ax1.set_title('主趋势图(跨三列)')
ax1.grid(True, alpha=0.3)
# 第二个图占据第二行第一列
ax2 = plt.subplot2grid((3, 3), (1, 0))
ax2.hist(np.random.randn(1000), bins=30, edgecolor='black', alpha=0.7) # 直方图
ax2.set_title('分布直方图')
# 第三个图占据第二行第二列
ax3 = plt.subplot2grid((3, 3), (1, 1))
categories = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
values = [23, 45, 12, 67, 34]
ax3.bar(categories, values, color='orange')
ax3.set_title('每日数据')
# 第四个图占据第二行第三列及第三行第三列(跨2行1列)
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
sizes = [35, 25, 20, 20]
ax4.pie(sizes, labels=['North', 'South', 'East', 'West'], autopct='%1.0f%%', startangle=140)
ax4.set_title('区域占比')
# 第五个图占据第三行第一、二列(跨1行2列)
ax5 = plt.subplot2grid((3, 3), (2, 0), colspan=2)
x_scatter = np.random.rand(50) * 10
y_scatter = x_scatter * 0.5 + np.random.randn(50) * 2
ax5.scatter(x_scatter, y_scatter, alpha=0.6)
ax5.set_xlabel('X')
ax5.set_ylabel('Y')
ax5.set_title('散点图(跨两列)')
plt.tight_layout()
plt.show()
plt.subplot2grid(shape, loc, rowspan=1, colspan=1) 中,shape 指定网格总体形状(行,列),loc 指定子图起始位置(行,列),rowspan 和 colspan 指定子图向下和向右占据的格子数。这种方法给了你极大的布局自由度,可以创建出满足各种复杂需求的仪表板视图。
8. 让图表“活”起来:保存、样式与实战建议
画好图表只是第一步,如何把它用起来,让它更好地为你服务,这里面还有不少门道。
8.1 保存你的劳动成果
在Jupyter Notebook里,图表会直接显示在单元格下方。但更多时候,我们需要把图表保存为图片文件,插入到报告、论文或PPT中。使用 plt.savefig() 函数可以轻松实现。
# 先创建一个漂亮的图表
fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label='sin(x)', linewidth=2)
ax.plot(x, np.cos(x), label='cos(x)', linestyle='--')
ax.set_title('三角函数对比')
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.legend()
ax.grid(True, alpha=0.3)
# 保存图表
plt.savefig('my_first_chart.png', dpi=300, bbox_inches='tight')
print("图表已保存为 'my_first_chart.png'")
savefig 有几个关键参数:dpi(每英寸点数)控制图片分辨率,用于印刷或高清展示时建议设为300或更高。bbox_inches='tight' 是我几乎每次都用的参数,它能自动裁剪掉图表周围多余的空白区域,让保存的图片紧凑又专业。你还可以指定格式,如 'my_chart.jpg'、'my_chart.pdf'、'my_chart.svg'(矢量格式,无限放大不失真)。
8.2 使用预定义样式快速美化
Matplotlib 自带了一系列预定义样式,可以一键改变图表的外观风格,省去你手动调整颜色、字体、网格的麻烦。
# 查看所有可用的样式
print(plt.style.available)
# 应用一个样式
plt.style.use('seaborn-v0_8-darkgrid') # 使用seaborn风格的深色网格样式
# 在样式下重新绘图
fig, ax = plt.subplots()
x = np.arange(10)
ax.plot(x, x**2, 'o-', label='二次函数')
ax.plot(x, x**1.5, 's-', label='1.5次函数')
ax.set_title('使用预定义样式的图表')
ax.legend()
plt.show()
常用的样式还有 'ggplot'(模仿R语言ggplot2包风格)、'fivethirtyeight'(模仿FiveThirtyEight网站风格)、'grayscale'(灰度风格)等。你可以多尝试几种,找到最适合你报告或审美的那一款。使用 plt.style.use('default') 可以切换回默认样式。
8.3 我踩过的坑与给你的建议
最后,分享几个从实际项目中总结出来的经验,希望能帮你少走弯路。
关于中文显示: 这是几乎所有新手都会遇到的第一个“坑”。Matplotlib默认不支持中文字体,直接使用中文会显示为方框。解决方法是在绘图前设置中文字体。一个比较通用的方法是:
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans'] # 指定字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
如果你在Linux系统或特定环境下,可能需要指定字体文件的完整路径。
关于图形大小和比例: 在 plt.subplots() 或 plt.figure() 时就用 figsize=(width, height) 设定好画布尺寸。记住一个原则:用于宽屏PPT的图可以宽一些(如16:9),用于论文的图可能需要考虑期刊的栏宽限制。
关于代码组织: 当图表变得复杂时,不要把所有的 plt.xxx() 调用都堆在一起。使用面向对象方式(fig, ax),将创建图形、绘制数据、添加装饰(标题、标签、图例)的代码分块组织,这样可读性和可维护性会好很多。
最重要的建议:多练,多改。 不要只看代码,一定要亲手敲一遍,然后尝试修改里面的每一个参数——改颜色、改线宽、改标记、改布局。可视化既是一门技术,也是一门艺术,你的审美和判断力会在一次次调试中快速提升。遇到问题,多去Matplotlib官网的Gallery(示例库)看看,那里有成千上万的例子和对应的源代码,是最好的学习资料。
更多推荐
所有评论(0)