让简单的绘图变简单,让复杂的绘图变可能

Matplotlib 并非孤立的工具,而是整个 Python 数据科学生态(如 NumPy、Pandas、Scikit-learn)的 “可视化接口”—— 几乎所有主流数据库(如 Pandas 的 plot() 方法)的底层绘图逻辑,本质上都是通过 Matplotlib 实现的。

核心作用:将数据转换为直观的图形,帮助用户理解数据规律、趋势或分布,常用于数据分析报告、学术论文、商业演示等场景。

Matplotlib 的绘图逻辑围绕两个核心对象展开:

  • Figure:代表整个 “画布”,是所有图表元素的容器(可以理解为一张白纸)。
  • Axes:代表画布上的 “子图区域”(一个画布可包含多个子图),是实际绘图的区域(如折线图、柱状图绘制在 Axes 上)。

常用的两种绘图接口:

  1. 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()  # 显示图表
    
  2. 面向对象接口(进阶):显式创建 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()

核心优势:

  1. 高度可定制:从坐标轴刻度、颜色、字体到图例位置、图形样式,均可通过参数精确控制,满足学术论文、商业报告等高标准需求。
  2. 兼容性强:与 NumPy、Pandas 无缝衔接(可直接传入数组或 DataFrame 数据),支持 Jupyter Notebook 嵌入显示,输出格式包括 PNG、SVG(矢量图)、PDF 等。
  3. 生态完善:作为基础库,可与 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)。

“既然选择了远方,便只顾风雨兼程。”—— 汪国真

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐