目录
一、为什么 Pandas 能画图
1. 底层机制
2. 为什么优先使用 Pandas 绘图
二、单变量图表绘制
1. 折线图
2. 柱状图
3. 直方图
4. 饼图
5. 面积图
三、双变量与多列数据可视化
1. 散点图
2. 蜂巢图
3. 堆叠图
四、综合案例
1. 模拟数据准备
2. 步骤一:总体大盘分析
3. 步骤二:品类结构拆解
4. 步骤三:归因与相关性探查
五、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() 接管后续定制
# 简单的极速绘图示例 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 时默认绘制折线图),最常用于展示随时间变化的趋势
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()(当分类名称较长时使用)
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)
# 绘制服从正态分布的数据 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(是否显示图例)
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 线)
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')
代码示例
# 构建示例数据 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')
代码示例
# 生成大样本正态分布数据 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)
代码示例
# 创建多列季度数据 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
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 年的总体销售趋势如何?是否存在明显的季节性波动?
# 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?各类别的销售占比随时间如何变化?
# 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)的成交?
# 绘制折扣率与销售额的散点图 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 数据分析的核心知识体系,掌握了数据读取、清洗、转换、统计分析以及可视化展示等完整的数据分析流程,为后续学习机器学习、深度学习以及人工智能等更高级的内容奠定了坚实的基础
希望本系列能够帮助大家建立完整的数据分析思维,不仅学会各类库和函数的使用,更能够运用这些工具解决实际问题,在实践中不断提升自己的数据分析能力