Python 数据可视化的 “基石”--Matplotlib
·
让简单的绘图变简单,让复杂的绘图变可能
Matplotlib 并非孤立的工具,而是整个 Python 数据科学生态(如 NumPy、Pandas、Scikit-learn)的 “可视化接口”—— 几乎所有主流数据库(如 Pandas 的 plot() 方法)的底层绘图逻辑,本质上都是通过 Matplotlib 实现的。
核心作用:将数据转换为直观的图形,帮助用户理解数据规律、趋势或分布,常用于数据分析报告、学术论文、商业演示等场景。
Matplotlib 的绘图逻辑围绕两个核心对象展开:
Figure:代表整个 “画布”,是所有图表元素的容器(可以理解为一张白纸)。Axes:代表画布上的 “子图区域”(一个画布可包含多个子图),是实际绘图的区域(如折线图、柱状图绘制在Axes上)。
常用的两种绘图接口:
-
pyplot接口(入门):通过matplotlib.pyplot模块的函数(如plt.plot()、plt.bar())快速绘图,适合简单场景或交互式调试。import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) # 生成0-10的100个点 y = np.sin(x) plt.plot(x, y) # 绘制折线图 plt.xlabel('X轴') # 添加X轴标签 plt.ylabel('Y轴') # 添加Y轴标签 plt.title('正弦曲线') # 添加标题 plt.show() # 显示图表 -
面向对象接口(进阶):显式创建
Figure和Axes对象,精确控制子图布局和细节,适合复杂图表(如多子图、定制化样式)。fig, ax = plt.subplots(figsize=(8, 4)) # 创建画布和子图,指定尺寸 ax.plot(x, y, color='red', linestyle='--') # 在子图上绘图,设置样式 ax.set_xlabel('X轴', fontsize=12) # 子图X轴标签 ax.set_title('正弦曲线(面向对象接口)') fig.show()
核心优势:
- 高度可定制:从坐标轴刻度、颜色、字体到图例位置、图形样式,均可通过参数精确控制,满足学术论文、商业报告等高标准需求。
- 兼容性强:与 NumPy、Pandas 无缝衔接(可直接传入数组或 DataFrame 数据),支持 Jupyter Notebook 嵌入显示,输出格式包括 PNG、SVG(矢量图)、PDF 等。
- 生态完善:作为基础库,可与 Seaborn(美化样式)、Plotly(交互式图表)等工具配合,弥补原生功能短板(如默认样式较陈旧、缺乏交互性)。
支持的图表类型:
折线图 (plot)- 查看数据趋势变化 饼图/环形图 (pie) - 查看各部分占比关系 柱状图 (bar/barh) - 比较不同类别数据的大小 散点图 (scatter) - 分析两个变量之间的关系 直方图 (hist) - 查看数据的分布情况 箱线图(boxplot)- 查看异常数据 创建图表的基本步骤: 1. 引入库 import matplotlib.pyplot as plt 2. 创建画布和图表 plt.figure(figsize=(10, 5)) 3. 绘制图表内容 ... 具体的绘图代码 4. 显示图表 plt.show()
一、折线图(plot):查看数据趋势变化
import matplotlib.pyplot as plt
import numpy as np
# 数据:时间(天)与销量
days = np.arange(1, 11) # 1-10天
sales_a = [20, 35, 30, 45, 50, 60, 55, 70, 80, 90] # 产品A销量
sales_b = [15, 25, 40, 35, 45, 55, 65, 60, 75, 85] # 产品B销量
# 创建画布和子图
plt.figure(figsize=(10, 5))
# 绘制折线图(可叠加多条线)
plt.plot(days, sales_a, label='产品A', color='blue', marker='o', linestyle='-')
plt.plot(days, sales_b, label='产品B', color='red', marker='s', linestyle='--')
# 添加标签和标题
plt.xlabel('天数')
plt.ylabel('销量(件)')
plt.title('产品销量趋势图')
plt.legend() # 显示图例
plt.grid(alpha=0.3) # 添加网格线(透明度0.3)
plt.show()
关键参数:
marker:数据点标记(o圆圈、s正方形等);linestyle:线条样式(-实线、--虚线等);label:线条标签(配合legend()显示图例)。
二、饼图 / 环形图(pie):查看各部分占比关系
import matplotlib.pyplot as plt
# 数据:各渠道用户占比
channels = ['官网', 'APP', '小程序', '第三方平台']
users = [30, 25, 20, 25] # 百分比
colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99'] # 自定义颜色
# 1. 饼图
plt.figure(figsize=(12, 5))
plt.subplot(121) # 1行2列第1个子图
plt.pie(users, labels=channels, colors=colors, autopct='%1.1f%%',
startangle=90, explode=[0.1, 0, 0, 0]) # 突出显示第1部分
plt.title('用户来源占比(饼图)')
# 2. 环形图(通过 wedgeprops 设置内半径)
plt.subplot(122)
plt.pie(users, labels=channels, colors=colors, autopct='%1.1f%%',
wedgeprops=dict(width=0.3)) # 内半径0.3(环形宽度)
plt.title('用户来源占比(环形图)')
plt.tight_layout() # 自动调整布局
plt.show()
关键参数:
autopct:显示百分比(%1.1f%%表示保留 1 位小数);explode:设置某部分的偏移量(突出显示);wedgeprops=dict(width=0.3):环形图核心参数(控制环的宽度)。
三、柱状图(bar/barh):比较不同类别数据的大小
import matplotlib.pyplot as plt
import numpy as np
# 数据:不同城市的销售额
cities = ['北京', '上海', '广州', '深圳']
sales_2023 = [500, 650, 420, 580] # 2023年销售额(万元)
sales_2024 = [580, 720, 490, 650] # 2024年销售额
# 垂直柱状图(两组数据对比)
x = np.arange(len(cities)) # 城市位置索引
width = 0.35 # 柱子宽度
plt.figure(figsize=(10, 6))
plt.bar(x - width/2, sales_2023, width, label='2023年')
plt.bar(x + width/2, sales_2024, width, label='2024年')
# 设置x轴标签和刻度
plt.xlabel('城市')
plt.ylabel('销售额(万元)')
plt.title('各城市销售额对比')
plt.xticks(x, cities) # 用城市名替换默认刻度
plt.legend()
plt.show()
# 水平柱状图(单独展示2024年数据)
plt.figure(figsize=(10, 4))
plt.barh(cities, sales_2024, color='green') # barh(类别, 数值)
plt.xlabel('销售额(万元)')
plt.title('2024年各城市销售额(水平柱状图)')
plt.show()
关键技巧:
- 多组数据对比时,通过
x ± width/2调整柱子位置,避免重叠; - 类别名称较长时,用
barh(水平柱状图)更易显示标签。
四、散点图(scatter):分析两个变量之间的关系
import matplotlib.pyplot as plt
import numpy as np
# 数据:广告投入(万元)与销量(千件)
np.random.seed(42) # 固定随机数,确保结果一致
ad_cost = np.random.randint(10, 100, 50) # 50个广告投入数据
sales = 2 * ad_cost + np.random.randint(-10, 10, 50) # 销量(大致正相关)
profit = sales * 0.8 - ad_cost * 0.3 # 利润(作为点的颜色映射)
# 绘制散点图
plt.figure(figsize=(10, 6))
scatter = plt.scatter(ad_cost, sales, c=profit, cmap='coolwarm',
s=sales*5, alpha=0.7, edgecolors='black') # s控制点大小
# 添加颜色条(表示利润)
plt.colorbar(scatter, label='利润(万元)')
plt.xlabel('广告投入(万元)')
plt.ylabel('销量(千件)')
plt.title('广告投入与销量的关系(点大小=销量,颜色=利润)')
plt.grid(alpha=0.3)
plt.show()
关键参数:
c:点的颜色(可映射第三变量,配合cmap设置颜色主题);s:点的大小(可映射第四变量);alpha:透明度(避免点重叠时遮挡)。
五、直方图(hist):查看数据的分布情况
import matplotlib.pyplot as plt
import numpy as np
# 数据:1000名学生的考试分数(正态分布)
np.random.seed(42)
scores = np.random.normal(loc=70, scale=10, size=1000) # 均值70,标准差10
# 绘制直方图
plt.figure(figsize=(10, 6))
n, bins, patches = plt.hist(scores, bins=15, density=True, alpha=0.7, color='skyblue',
edgecolor='black') # bins=区间数量
# 添加概率密度曲线(更直观展示分布)
from scipy.stats import norm
mu, sigma = norm.fit(scores) # 拟合正态分布参数
x = np.linspace(scores.min(), scores.max(), 100)
plt.plot(x, norm.pdf(x, mu, sigma), 'r--', linewidth=2) # 绘制理论分布曲线
plt.xlabel('分数')
plt.ylabel('频率/概率')
plt.title('学生考试分数分布(直方图+正态曲线)')
plt.axvline(mu, color='green', linestyle=':', label=f'均值={mu:.1f}') # 标记均值
plt.legend()
plt.show()
关键参数:
bins:区间数量(过小可能模糊分布,过大可能出现噪声);density=True:将频数转换为概率密度(总面积为 1)。
六、箱线图(boxplot):查看异常数据
import matplotlib.pyplot as plt
import numpy as np
# 数据:3个班级的成绩(含异常值)
np.random.seed(42)
class1 = np.random.normal(75, 8, 50)
class2 = np.random.normal(68, 10, 50)
class3 = np.random.normal(82, 6, 50)
class3 = np.append(class3, [30, 25, 120]) # 给三班添加3个异常值
# 绘制箱线图
plt.figure(figsize=(10, 6))
box_data = [class1, class2, class3]
labels = ['一班', '二班', '三班']
bplot = plt.boxplot(box_data, labels=labels, patch_artist=True, # patch_artist=True可填充颜色
boxprops=dict(facecolor='lightblue'), # 箱体颜色
flierprops=dict(marker='o', color='red', alpha=0.5)) # 异常值样式
plt.ylabel('分数')
plt.title('各班成绩分布与异常值检测')
plt.grid(axis='y', alpha=0.3)
plt.show()
解读要点:
- 箱体越长,数据离散程度越高;
- 中位数位置偏上 / 下,说明数据左偏 / 右偏;
- 红色点为异常值(通常定义为 <Q1-1.5×IQR 或> Q3+1.5×IQR,IQR=Q3-Q1)。
“既然选择了远方,便只顾风雨兼程。”—— 汪国真
更多推荐


所有评论(0)