Day 05 · Matplotlib 基础:折线图、柱状图、饼图、散点图
「AI Python 系列」第 02 栏 · AI+数据可视化
全栏 15 篇 · 零成本跟完 🍃
作者:梅雅达编程笔记
首发:CSDN
摘要: 从这篇开始正式画图。
Matplotlib是 Python 可视化的一切基础,后面的Seaborn、Pyecharts都是在它之上封装的。本篇用同一份电商销售数据,分别画出四种最常用的基础图表:折线图看趋势、柱状图看对比、饼图看占比、散点图看关系。每种图都给出完整代码和适用场景说明,拿来就能用。
数据洗干净了,终于可以画图了。
Matplotlib 是 Python 可视化世界的地基。不管你以后用 seaborn、pyecharts 还是 plotly,底层都是它。搞懂了 matplotlib,其他库学起来特别快。
一、准备数据
后面所有图都用这份数据:
import pandas as pd
import matplotlib.pyplot as plt
# 设置中文显示(每次都记得加,不然中文变方块)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False
# 月度销售数据
months = ['1月', '2月', '3月', '4月', '5月', '6月',
'7月', '8月', '9月', '10月', '11月', '12月']
sales = [12.3, 10.1, 15.8, 14.2, 18.6, 22.1,
19.5, 24.3, 21.7, 26.8, 30.2, 35.5]
# 商品分类数据
products = ['商品A', '商品B', '商品C', '商品D']
category_sales = [320, 280, 195, 205]
# 渠道占比
channels = ['线上', '线下', '分销']
channel_share = [55, 30, 15]
# 价格-销量关系(散点图用)
prices = [59, 79, 99, 129, 159, 199, 249, 299]
volumes = [420, 350, 280, 180, 120, 85, 45, 20]
二、折线图:看趋势
折线图最适合展示随时间变化的趋势。
plt.figure(figsize=(10, 5))
plt.plot(months, sales, marker='o', color='#2196F3', linewidth=2)
plt.title('全年月度销售额趋势', fontsize=14, fontweight='bold')
plt.ylabel('销售额(万元)', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('折线图_月度销售趋势.png', dpi=150)
plt.show()

关键参数解释:
marker='o':每个数据点画一个圆点color='#2196F3':颜色用十六进制,这个是我觉得最好看的蓝色之一linewidth=2:线宽,默认是 1,2 会粗一点更醒目alpha=0.3:网格线的透明度,太实了会干扰视线
多条折线对比:
# 两条产品线对比
sales_a = [5.2, 4.8, 6.1, 5.5, 7.2, 8.5, 7.8, 9.1, 8.3, 10.2, 11.5, 13.2]
sales_b = [4.1, 3.5, 5.2, 4.8, 6.5, 7.8, 6.9, 8.5, 7.5, 9.8, 11.0, 12.8]
plt.figure(figsize=(10, 5))
plt.plot(months, sales_a, marker='o', label='商品A', color='#2196F3', linewidth=2)
plt.plot(months, sales_b, marker='s', label='商品B', color='#FF5722', linewidth=2)
plt.title('商品 A vs 商品 B 月度销售对比', fontsize=14, fontweight='bold')
plt.ylabel('销售额(万元)', fontsize=12)
plt.legend() # 显示图例
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('折线图_多线对比.png', dpi=150)
plt.show()

label + plt.legend() 是多条线的标配。
三、柱状图:看对比
柱状图最适合比较不同类别的数值大小。
# 基础柱状图
plt.figure(figsize=(8, 5))
plt.bar(products, category_sales, color=['#2196F3', '#FF5722', '#4CAF50', '#FFC107'])
plt.title('各商品年度销量对比', fontsize=14, fontweight='bold')
plt.ylabel('销量(件)', fontsize=12)
# 在每个柱子上标注数值
for i, (product, value) in enumerate(zip(products, category_sales)):
plt.text(i, value + 5, str(value), ha='center', fontsize=11)
plt.tight_layout()
plt.savefig('柱状图_商品对比.png', dpi=150)
plt.show()

横向柱状图(标签太长时更好用):
plt.figure(figsize=(8, 5))
plt.barh(products, category_sales, color=['#2196F3', '#FF5722', '#4CAF50', '#FFC107'])
plt.title('各商品年度销量对比', fontsize=14, fontweight='bold')
plt.xlabel('销量(件)', fontsize=12)
# 标注数值
for i, (product, value) in enumerate(zip(products, category_sales)):
plt.text(value + 5, i, str(value), va='center', fontsize=11)
plt.tight_layout()
plt.savefig('柱状图_横向.png', dpi=150)
plt.show()

分组柱状图(每个类别有多个对比项):
import numpy as np
# 各商品在各渠道的销量
data = {
'线上': [180, 150, 100, 110],
'线下': [100, 90, 65, 70],
'分销': [40, 40, 30, 25]
}
x = np.arange(len(products))
width = 0.25
fig, ax = plt.subplots(figsize=(10, 5))
bars1 = ax.bar(x - width, data['线上'], width, label='线上', color='#2196F3')
bars2 = ax.bar(x, data['线下'], width, label='线下', color='#FF5722')
bars3 = ax.bar(x + width, data['分销'], width, label='分销', color='#4CAF50')
ax.set_title('各商品分渠道销量对比', fontsize=14, fontweight='bold')
ax.set_xticks(x)
ax.set_xticklabels(products)
ax.legend()
plt.tight_layout()
plt.savefig('柱状图_分组.png', dpi=150)
plt.show()

四、饼图:看占比
饼图适合展示整体中各部分的比例。
plt.figure(figsize=(7, 7))
colors = ['#2196F3', '#FF5722', '#4CAF50']
# 基础饼图
plt.pie(channel_share, labels=channels, colors=colors,
autopct='%1.1f%%', # 显示百分比
startangle=90, # 起始角度
textprops={'fontsize': 13})
plt.title('销售渠道占比', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig('饼图_渠道占比.png', dpi=150)
plt.show()

突出显示某一块:
plt.figure(figsize=(7, 7))
explode = (0.05, 0, 0) # 第一块"拉出来"一点
plt.pie(channel_share, labels=channels, colors=colors,
autopct='%1.1f%%', startangle=90,
explode=explode,
textprops={'fontsize': 13})
plt.title('销售渠道占比(线上为主)', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig('饼图_突出显示.png', dpi=150)
plt.show()

💡 什么时候不用饼图? 分类超过 5-6 个的时候,饼图就挤成一团了。这时候换成横向柱状图更好。
五、散点图:看关系
散点图用来展示两个变量之间有没有关系。
plt.figure(figsize=(8, 6))
plt.scatter(prices, volumes, s=100, color='#2196F3', edgecolors='white', linewidth=1)
# 加上标签
for i, price in enumerate(prices):
plt.annotate(f'¥{price}', (price, volumes[i]),
textcoords="offset points", xytext=(5, 5), fontsize=9)
plt.title('价格 vs 销量:价格越高,卖得越少', fontsize=14, fontweight='bold')
plt.xlabel('价格(元)', fontsize=12)
plt.ylabel('销量(件)', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('散点图_价格vs销量.png', dpi=150)
plt.show()

一眼就能看出:价格越高,销量越低。这就是负相关。
加一条趋势线:
from scipy import stats
# 计算线性回归
slope, intercept, r_value, p_value, std_err = stats.linregress(prices, volumes)
line = [slope * x + intercept for x in prices]
plt.figure(figsize=(8, 6))
plt.scatter(prices, volumes, s=100, color='#2196F3', edgecolors='white',
linewidth=1, zorder=3)
plt.plot(prices, line, color='#FF5722', linewidth=2, linestyle='--',
label=f'趋势线 (R²={r_value**2:.2f})', zorder=2)
plt.title('价格 vs 销量(含趋势线)', fontsize=14, fontweight='bold')
plt.xlabel('价格(元)', fontsize=12)
plt.ylabel('销量(件)', fontsize=12)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('散点图_趋势线.png', dpi=150)
plt.show()
R² 越接近 1,说明两个变量的关系越强。

六、四大图表适用场景速查
| 图表类型 | 一句话用途 | 典型场景 |
|---|---|---|
| 折线图 | 看趋势 | 月度销售走势、日活变化 |
| 柱状图 | 看对比 | 各产品销量、各部门业绩 |
| 饼图 | 看占比 | 渠道分布、成本构成 |
| 散点图 | 看关系 | 价格与销量、广告投入与转化 |
记住这个表,大部分场景选图就不会错。
七、通用小技巧
保存高清图片:
plt.savefig('图表.png', dpi=150, bbox_inches='tight')
# dpi=150 足够清晰,要打印用 dpi=300
# bbox_inches='tight' 去掉多余白边
子图布局(一张图里放多个小图):
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
axes[0, 0].plot(months, sales, color='#2196F3')
axes[0, 0].set_title('月度趋势')
axes[0, 1].bar(products, category_sales, color='#FF5722')
axes[0, 1].set_title('商品对比')
axes[1, 0].pie(channel_share, labels=channels, autopct='%1.1f%%')
axes[1, 0].set_title('渠道占比')
axes[1, 1].scatter(prices, volumes, color='#4CAF50')
axes[1, 1].set_title('价格vs销量')
plt.tight_layout()
plt.savefig('四图合一.png', dpi=150)
plt.show()

八、小结
四大基础图表画完了。核心代码其实都很短,关键是知道什么场景用什么图:
- 有时间维度 → 折线图
- 要比较大小 → 柱状图
- 要看比例 → 饼图
- 要看两个变量的关系 → 散点图
Matplotlib 的 API 很多,不需要全记住。记住常用的,遇到不会的查文档或者问 AI 就行。
下一篇讲怎么把这些基础图表变好看——配色、标注、布局这些"审美"层面的东西。
下期预告: Day 06 图表美化——配色方案、标注技巧、子图布局、中文显示问题解决,让你的图从"能用"变成"好看"。
往期回顾
Day 01 · 数据可视化到底在干啥?为什么 AI 让它变简单了
Day 03 · Pandas 快速上手:读取、清洗、整理数据
Day 04 · 数据清洗:缺失值、异常值、重复值一站式处理
专栏
-「AI Python 系列」第 02 栏 ·AI+数据可视化(连载中)
-「AI Python 系列」第 01 栏 · AI+自动化办公(连载中)
-「AI Python 系列」第 03 栏 · Python 爬虫实战(连载中)
资源领取
- 关注作者获取本栏完整代码和数据集
原创声明:本文为梅雅达编程笔记原创作品,未经允许不得转载。
更多推荐


所有评论(0)