目录
[一、为什么 Pandas 能画图](#一、为什么 Pandas 能画图)
[1. 底层机制](#1. 底层机制)
[2. 为什么优先使用 Pandas 绘图](#2. 为什么优先使用 Pandas 绘图)
[1. 折线图](#1. 折线图)
[2. 柱状图](#2. 柱状图)
[3. 直方图](#3. 直方图)
[4. 饼图](#4. 饼图)
[5. 面积图](#5. 面积图)
[1. 散点图](#1. 散点图)
[2. 蜂巢图](#2. 蜂巢图)
[3. 堆叠图](#3. 堆叠图)
[1. 模拟数据准备](#1. 模拟数据准备)
[2. 步骤一:总体大盘分析](#2. 步骤一:总体大盘分析)
[3. 步骤二:品类结构拆解](#3. 步骤二:品类结构拆解)
[4. 步骤三:归因与相关性探查](#4. 步骤三:归因与相关性探查)
[五、Pandas、Matplotlib、Seaborn 对比](#五、Pandas、Matplotlib、Seaborn 对比)
一、为什么 Pandas 能画图
在数据分析流程中,数据通常以 DataFrame 或 Series 的结构存储于 Pandas 中。在探索数据时,最顺手的绘图方式并不是直接写 plt.plot(),而是直接在数据对象后加上 .plot()
Pandas 之所以具备内置的绘图能力,并非因为它自己开发了一套独立的渲染引擎,而是因为它在底层集成了 Matplotlib
1. 底层机制
Pandas 的 .plot() 方法本质上是对 Matplotlib 接口的高阶封装
当你执行 df.plot() 时,Pandas 在后台完成了以下自动化工作:
-
提取坐标与标签:将 DataFrame 的索引自动映射为 X 轴,将数据列映射为 Y 轴或不同的数据序列
-
构建图表:根据列名自动生成图例、根据索引类型自动格式化坐标轴刻度
-
调用 Matplotlib 渲染:将处理好的数据与样式参数打包传递给 Matplotlib 进行底层的画布绘制与图形渲染
-
返回 Axes 对象:.plot() 方法的返回值正是 Matplotlib 的 Axes 对象

2. 为什么优先使用 Pandas 绘图
直接使用 Pandas 绘图相比直接调用底层 Matplotlib 具有明显的效率优势:
-
零数据转换成本:无需手动通过 .values 提取 NumPy 数组,也不必写循环去遍历多列数据
-
支持时间序列:Pandas 对时间索引有极佳的适配,能自动进行时间轴缩放与日期格式化
-
接轨底层扩展:由于返回的是 Axes 对象,若内置参数无法满足美化需求,可随时用标准的 ax.set_title() 或 plt.show() 接管后续定制
python
# 简单的极速绘图示例
df = pd.DataFrame({'Sales': [100, 120, 140]}, index=['Jan', 'Feb', 'Mar'])
# 仅需一步,自动将 index 作为 X 轴,Sales 作为 Y 轴
ax = df.plot(figsize=(6, 3.5))
# 随时用 Matplotlib 原生方法叠加微调
ax.set_ylabel("USD")
plt.show()
二、单变量图表绘制
在 Pandas 中,绘制单变量图表有两种等价的调用语法:
-
函数参数模式:series.plot(kind='图表类型')
-
方法链模式:series.plot.<kind>()(更加推荐,代码提示友好)
本章介绍五种最常用的单变量图表及其适用场景
1. 折线图
折线图是 plot() 的默认图表类型(即不传 kind 时默认绘制折线图),最常用于展示随时间变化的趋势
python
import pandas as pd
import matplotlib.pyplot as plt
# 构建带时间索引的单列数据
dates = pd.date_range("2026-01-01", periods=6, freq="ME")
sales = pd.Series([120, 135, 125, 145, 160, 175], index=dates)
# 绘制折线图
ax = sales.plot.line(figsize=(7, 3.5), color="#1f77b4", marker="o")
ax.set_ylabel("Sales Volume")
plt.grid(True, linestyle=":", alpha=0.6)
plt.show()
输出结果:

2. 柱状图
柱状图用于展示不同类别之间的大小比较。处理离散文本分类或对频数统计结果绘图时非常高效
-
垂直柱状图:series.plot.bar()
-
水平条形图:series.plot.barh()(当分类名称较长时使用)
python
category_sales = pd.Series([450, 320, 280, 410], index=["East", "West", "South", "North"])
# 绘制水平柱状图
ax = category_sales.plot.bar(figsize=(7, 3.5), color="#4c8be2", width=0.6)
ax.set_xlabel("Revenue (k USD)")
plt.show()
输出结果:

3. 直方图
直方图用于展示连续数值型变量的频数分布形态与聚集区间。
- 关键参数:bins(分箱数量,默认 10)
python
# 绘制服从正态分布的数据
np.random.seed(42)
scores = pd.Series(np.random.normal(loc=75, scale=10, size=200))
# 绘制直方图
ax = scores.plot.hist(bins=15, figsize=(7, 3.5), color="#2b5c8f", edgecolor="black")
ax.set_xlabel("Score")
plt.show()
输出结果:

4. 饼图
饼图用于呈现离散分类占总体的比例关系
- 关键参数:autopct(数值百分比格式)、legend(是否显示图例)
python
market_share = pd.Series([35, 25, 20, 20],
index=["Brand A", "Brand B", "Brand C", "Others"])
# 绘制饼图
ax = market_share.plot.pie(
figsize=(5, 5),
autopct="%.1f%%",
startangle=90,
colors=["#5b9bd5", "#ed7d31", "#a5a5a5", "#ffc000"]
)
ax.set_ylabel("") # 隐藏默认生成的 Series 列名标签
plt.show()
输出结果:

5. 面积图
面积图在折线图的基础上填充了下方的区域,用于突出显示总体累积规模与量级
- 关键参数:alpha(透明度,避免遮挡 grid 线)
python
traffic = pd.Series([100, 250, 400, 300, 500, 700], index=range(1, 7))
# 绘制面积图
ax = traffic.plot.area(figsize=(7, 3.5), color="#5b9bd5", alpha=0.4)
ax.set_xlabel("Hour")
ax.set_ylabel("Active Users")
plt.show()
输出结果:

| 方法 | 适用于 | 关注点 | 常用调参 |
|---|---|---|---|
| plot.line() | 时间序列 / 连续数值 | 趋势变化 | marker, linestyle |
| plot.bar() / .barh() | 离散分类与对应数值 | 类别间数值对比 | width, color |
| plot.hist() | 单个连续数值变量 | 数据分布与聚集区 | bins |
| plot.pie() | 离散分类及其占比 | 构成比例 | autopct, startangle |
| plot.area() | 连续数值序列 | 体积与累计规模 | alpha |
三、双变量与多列数据可视化
在数据分析中,双变量与多列数据的比较能够揭示特征之间的相关性、组合结构及趋势差异。DataFrame 支持直接将多列数据映射至坐标轴或堆叠组中,无需复杂的数据重构即可完成双变量可视化
1. 散点图
散点图用于展示两个连续数值变量之间的分布关系与相关趋势。与单变量绘图不同,调用 DataFrame.plot.scatter() 时必须显式指定 x 和 y 的列名
关键参数说明
-
x, y:必需参数,分别指定映射到 X 轴和 Y 轴的列名字符串
-
c:可传入第三个列名,用颜色深浅映射数值大小(实现三维数据展示)
-
s:指定散点大小(标量或数组/列名)
-
cmap:当指定 c 为连续数值列时,指定颜色渐变表(如 'viridis')
代码示例
python
# 构建示例数据
np.random.seed(42)
df = pd.DataFrame({
'Ad_Budget': np.random.uniform(10, 100, 50),
'Sales': np.random.uniform(20, 150, 50),
'ROI': np.random.uniform(1, 5, 50)
})
# 绘制 X=广告预算, Y=销售额, 颜色=ROI 的散点图
ax = df.plot.scatter(
x='Ad_Budget',
y='Sales',
c='ROI',
cmap='viridis',
s=50,
figsize=(7, 4)
)
ax.set_xlabel("Ad Budget (k USD)")
ax.set_ylabel("Sales Volume")
plt.show()
输出结果:

2. 蜂巢图
当数据量过大(如数万条记录)时,普通散点图会由于点位过度重叠而失去可读性。plot.hexbin() 将二维空间切分为六边形网格,通过颜色深浅表达落入网格内的点数频数
关键参数说明
-
x, y:必需参数,二元连续变量列名
-
gridsize:指定 X 轴方向的六边形网格数量。数值越大网格越细致
-
cmap:映射密度的颜色表(如 'Blues')
代码示例
python
# 生成大样本正态分布数据
np.random.seed(42)
x_data = np.random.randn(5000)
y_data = x_data * 0.8 + np.random.randn(5000) * 0.5
df_large = pd.DataFrame({'Feature_X': x_data, 'Feature_Y': y_data})
# 绘制蜂巢图
ax = df_large.plot.hexbin(
x='Feature_X',
y='Feature_Y',
gridsize=25,
cmap='Blues',
figsize=(7, 4)
)
plt.show()
输出结果:

3. 堆叠图
当需要展示多个分类在总总量中的构成比例变化时,可在柱状图或面积图中传入 stacked=True 参数
Pandas 会自动将 DataFrame 的每一列作为一个堆叠层,按照列顺序逐层向上累加
关键参数说明
-
stacked:布尔值,设为 True 时开启堆叠模式(默认为 False 彼此并排)
-
alpha:透明度控制(在堆叠面积图中尤为重要,建议设为 0.5 - 0.8)
代码示例
python
# 创建多列季度数据
quarterly_sales = pd.DataFrame({
'Product_A': [120, 150, 170, 190],
'Product_B': [90, 110, 130, 140],
'Product_C': [50, 60, 55, 70]
}, index=['Q1', 'Q2', 'Q3', 'Q4'])
# 绘制堆叠柱状图与堆叠面积图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4.5))
# 1. 堆叠柱状图:展现各季度总营收及产品构成
quarterly_sales.plot.bar(stacked=True, ax=ax1)
ax1.set_ylabel("Sales Volume")
ax1.tick_params(axis='x', rotation=0)
# 2. 堆叠面积图:展现趋势及累积体量
quarterly_sales.plot.area(stacked=True, alpha=0.7, ax=ax2)
ax2.set_ylabel("Cumulative Volume")
plt.show()
输出结果:

| 图表类型 | 调用 API | 适用场景 | 核心优势 |
|---|---|---|---|
| 散点图 | df.plot.scatter(x, y) | 双连续数值相关性分析 | 支持用 c 和 s 额外扩展颜色与大小维度 |
| 蜂巢图 | df.plot.hexbin(x, y) | 海量数据点相关性分析 | 解决数据点严重重叠遮挡的问题 |
| 堆叠柱状图 | df.plot.bar(stacked=True) | 离散组别下的总量及结构占比 | 直观展示分类总量与内部构成关系 |
| 堆叠面积图 | df.plot.area(stacked=True) | 连续序列下的总量与构成变化 | 强调时间推移下的累积规模与趋势 |
四、综合案例
在实际工程项目中,数据可视化很少是单独绘制一张孤立的图表,而是需要遵循"全貌 -> 结构 -> 关联"的探索逻辑,针对业务问题输出一套完整的分析仪表盘。
本章通过一个电商业务销售数据分析案例,使用 Pandas 内置的绘图 API,一步步完成从数据准备到多图联合呈现场景的完整落地
1. 模拟数据准备
假设我们获得了某电商平台 2025 年全年的订单数据,包含交易日期、商品品类、销售额以及折扣率等维度。我们首先构建包含这几项核心特征的 DataFrame
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 1. 模拟 2025 全年每日订单数据
np.random.seed(42)
date_range = pd.date_range(start="2025-01-01", end="2025-12-31", freq="D")
n = len(date_range)
categories = ["Electronics", "Clothing", "Home & Kitchen", "Beauty"]
# 构建 DataFrame
df = pd.DataFrame({
"Date": np.random.choice(date_range, size=1000),
"Category": np.random.choice(categories, size=1000, p=[0.4, 0.3, 0.2, 0.1]),
"Sales": np.random.exponential(scale=150, size=1000) + 20,
"Discount": np.random.uniform(0.05, 0.35, size=1000)
}).sort_values("Date").reset_index(drop=True)
# 设置日期索引以支持时间序列操作
df.set_index("Date", inplace=True)
2. 步骤一:总体大盘分析
第一步的目标是查看全局:2025 年的总体销售趋势如何?是否存在明显的季节性波动?
python
# 1. 按月聚合计算总销售额
monthly_sales = df["Sales"].resample("ME").sum()
# 2. 绘制月度销售趋势图
ax1 = monthly_sales.plot.line(
figsize=(8, 4),
color="#1f77b4",
marker="o",
linewidth=2,
title="2025 Monthly Total Sales Trend"
)
ax1.set_ylabel("Sales ($)")
ax1.grid(True, linestyle="--", alpha=0.5)
plt.show()
输出结果:

-
为什么这么做:
-
使用 df"Sales".resample("ME").sum() 将日频订单数据重采样为月度聚合指标
-
调用 .plot.line() 直接绘制时间序列折线图
-
-
有什么好处:
-
平滑噪声:日频数据波动极大,直接看日线会有极多尖刺;重采样到月频能够滤除日常噪声,精准捕捉季度或月度趋势
-
日期格式化:Pandas 能够自动识别 DatetimeIndex,X 轴的月份标签由 Matplotlib 自动格式化呈现,无需手动配置日期刻度
-
3. 步骤二:品类结构拆解
在了解了大盘趋势后,第二步需要回答:哪些品类贡献了主要的 sales?各类别的销售占比随时间如何变化?
python
# 1. 构建月度-品类透视表
category_pivot = df.pivot_table(
index=pd.Grouper(freq="ME"),
columns="Category",
values="Sales",
aggfunc="sum"
)
# 2. 绘制品类堆叠柱状图
ax2 = category_pivot.plot.bar(
stacked=True,
figsize=(9, 4.5),
colormap="Set2",
title="Monthly Sales Contribution by Category"
)
ax2.set_ylabel("Sales ($)")
ax2.set_xticklabels([d.strftime('%Y-%m') for d in category_pivot.index], rotation=45)
ax2.grid(axis="y", linestyle="--", alpha=0.5)
plt.legend(title="Category", bbox_to_anchor=(1.02, 1), loc="upper left")
plt.tight_layout()
plt.show()
输出结果:

-
为什么这么做:
-
通过 df.pivot_table() 将数据塑形为 "行=月份、列=品类" 的矩阵
-
传入 stacked=True 开启堆叠模式
-
-
有什么好处:
-
兼顾总量与构成:柱子的总高度代表该月总营收,柱子内部各色块的高度代表对应品类的贡献,能快速识别出主力品类
-
代码效率:通过 Pandas 的透视表与 stacked=True 结合,仅需两行代码就完成了多维数据拆解与堆叠图渲染,免去了手动循环画柱子的繁琐步骤
-
**4.**步骤三:归因与相关性探查
第三步分析业务归因:促销折扣(Discount)是否真正拉动了高客单价商品(Sales)的成交?
python
# 绘制折扣率与销售额的散点图
ax3 = df.plot.scatter(
x="Discount",
y="Sales",
c="Discount",
cmap="Reds",
s=30,
alpha=0.7,
figsize=(8, 4),
title="Discount Rate vs. Order Sales Amount"
)
ax3.set_xlabel("Discount Rate")
ax3.set_ylabel("Order Sales ($)")
ax3.grid(True, linestyle=":", alpha=0.6)
plt.show()
输出结果:

-
为什么这么做:
-
使用 df.plot.scatter() 指定 x="Discount" 与 y="Sales"
-
利用 c="Discount" 与 cmap="Reds" 让数据点的颜色与折扣力度绑定
-
-
有什么好处:
-
验证业务假设:能够直观观察高 Sales 订单是否集中在高折扣区(X 轴右侧),方便评估促销政策
-
发现异常值:散点图能一眼找出低折扣但高销售额的爆款订单,或者高折扣但销售额依然低迷的亏损订单
-
五、Pandas、Matplotlib、Seaborn 对比
在 Python 数据分析与可视化生态中,Matplotlib 、Seaborn 和 Pandas 内置绘图构成了最核心的三要素。三者并非替代关系,而是层层递进、互为补充的关系
-
Matplotlib 是底层基石,提供了像素级的图形控制力
-
Seaborn 是高阶统计可视化工具,封装了复杂的统计算法与现代色彩主题
-
Pandas 绘图是数据探索阶段的极速工具,与 DataFrame 结构无缝集成,操作效率极高
| 库名称 | 特点 | 优势 | 局限 | 适合使用场景 |
|---|---|---|---|---|
| Matplotlib | 最底层 API | 自由度极高,支持任意细节的像素级自定义 | 代码量大且冗长 | 复杂多图排版、特殊定制图表、出版级学术图表 |
| Seaborn | 美观统计图 | 内置高级统计逻辑,美学风格调和 | 对单独图形元素的微调仍需依赖 Matplotlib | 探索性统计分析、交叉特征对比 |
| Pandas | 简单快速分析 | 极简语法,直接绑定 DataFrame 的索引与列名 | 样式定制与高阶统计功能较弱 | 数据清洗与快速验证数据分布 |
最佳实践
在实际的 Python 数据分析工作流中,并不需要孤立地只选择某一个库,推荐的搭配流程为:
-
快速探索数据(Pandas):拿到原始 DataFrame 后,直接调用 df.plot() 或 df.plot.hist(),用最少的代码快速观察趋势、离群值与分布特征
-
深入挖掘关系(Seaborn):需要按多维度分组、查看变量间相关性时,切换为 Seaborn 进行高效的统计表达
-
输出成品图表(Matplotlib):当需要将图表放入 PPT、报告或论文时,使用 Matplotlib 调整 figsize、修改字体、设置图例位置以及去除无用边框,输出精细美化的成品
总结
本章学习了 Pandas 内置的数据可视化功能,掌握了柱状图、折线图、面积图、直方图、饼图、散点图、蜂窝图和堆叠图等常见图表的绘制方法,进一步体会了 Pandas 在快速探索性数据分析中的优势。通过对 Pandas、Matplotlib 和 Seaborn 三种可视化方式的学习,我们已经能够根据不同的数据分析需求,选择合适的工具完成数据展示与结果表达
至此,《Python 数据分析从入门到实战》系列正式完结。从数据分析基础、NumPy 数值计算、Pandas 数据处理,到 Matplotlib、Seaborn 和 Pandas 数据可视化,我们系统学习了 Python 数据分析的核心知识体系,掌握了数据读取、清洗、转换、统计分析以及可视化展示等完整的数据分析流程,为后续学习机器学习、深度学习以及人工智能等更高级的内容奠定了坚实的基础
希望本系列能够帮助大家建立完整的数据分析思维,不仅学会各类库和函数的使用,更能够运用这些工具解决实际问题,在实践中不断提升自己的数据分析能力
