知识点讲解
1. 为什么要做数据可视化?
人脑处理图像的速度比处理文字快 6 万倍。一张好的图表,能让老板在 3 秒内看懂数据趋势。做数据分析,最后一步通常就是把结果"画"出来。
2. 如何选择合适的图表?
- 折线图:看趋势变化(销售额随时间变化)
- 柱状图:比较不同类别的数值(各品类销售额对比)
- 饼图:看占比构成(各品类销售占比)
- 散点图:看两个变量的关系(价格 vs 销量)
- 热力图:看矩阵数据的密度(各地区各月份销售额)
- 箱线图:看数据分布和异常值
3. pandas 快速绘图
pandas 的 Series 和 DataFrame 都有 .plot() 方法,底层调用的是 Matplotlib,适合快速出图。
# Series 直接画折线图
df['销售额'].plot()
# DataFrame 画多线图
df.plot(x='月份', y=['销售额', '利润'])
4. Matplotlib 精细控制
Matplotlib 是 Python 最基础的绘图库,可以精确控制图表的每一个元素:标题、坐标轴、颜色、图例等。
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
plt.plot(x, y, label='销售额')
plt.title('月度销售额趋势')
plt.xlabel('月份')
plt.ylabel('金额(元)')
plt.legend()
plt.show()
5. Seaborn 统计图表
Seaborn 基于 Matplotlib,专门做统计可视化,代码更简洁,默认样式更美观。
import seaborn as sns
sns.heatmap(data, annot=True, fmt='.0f', cmap='YlOrRd')
sns.boxplot(x='品类', y='销售额', data=df)
完整代码示例
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体(Windows)
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# ========== 1. 创建模拟数据 ==========
np.random.seed(42)
# 月度销售数据
months = ['1月', '2月', '3月', '4月', '5月', '6月']
sales = [120, 135, 148, 162, 155, 178]
profit = [25, 30, 35, 40, 38, 45]
# 品类销售数据
categories = ['食品', '饮料', '日用品', '家电', '服装']
cat_sales = [320, 210, 180, 450, 290]
# 详细订单数据(用于散点图和箱线图)
n = 200
df = pd.DataFrame({
'品类': np.random.choice(categories, n),
'销售额': np.random.randint(50, 2000, n),
'数量': np.random.randint(1, 20, n),
'客户评分': np.random.randint(1, 6, n)
})
# 热力图数据:地区 × 月份
regions = ['华东', '华南', '华北', '西南']
heatmap_data = np.random.randint(50, 300, size=(4, 6))
heatmap_df = pd.DataFrame(heatmap_data, index=regions, columns=months)
# ========== 2. 折线图:月度销售趋势 ==========
plt.figure(figsize=(10, 5))
plt.plot(months, sales, marker='o', linewidth=2, label='销售额', color='#2563eb')
plt.plot(months, profit, marker='s', linewidth=2, label='利润', color='#16a34a')
plt.title('2024年上半年销售额与利润趋势', fontsize=14, fontweight='bold')
plt.xlabel('月份')
plt.ylabel('金额(万元)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# ========== 3. 柱状图:品类销售额对比 ==========
plt.figure(figsize=(10, 5))
colors = ['#2563eb', '#0ea5e9', '#8b5cf6', '#f59e0b', '#ef4444']
bars = plt.bar(categories, cat_sales, color=colors, edgecolor='white')
plt.title('各品类销售额对比', fontsize=14, fontweight='bold')
plt.xlabel('品类')
plt.ylabel('销售额(万元)')
# 在柱子上标注数值
for bar, val in zip(bars, cat_sales):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5,
str(val), ha='center', va='bottom', fontweight='bold')
plt.tight_layout()
plt.show()
# ========== 4. 饼图:品类销售占比 ==========
plt.figure(figsize=(8, 8))
plt.pie(cat_sales, labels=categories, autopct='%1.1f%%',
colors=colors, startangle=90, explode=(0.05, 0, 0, 0.05, 0))
plt.title('各品类销售占比', fontsize=14, fontweight='bold')
plt.show()
# ========== 5. 散点图:数量 vs 销售额 ==========
plt.figure(figsize=(10, 6))
for i, cat in enumerate(categories):
mask = df['品类'] == cat
plt.scatter(df[mask]['数量'], df[mask]['销售额'],
label=cat, alpha=0.6, s=50, color=colors[i])
plt.title('订单数量与销售额关系', fontsize=14, fontweight='bold')
plt.xlabel('数量')
plt.ylabel('销售额(元)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# ========== 6. 热力图:地区 × 月份 ==========
plt.figure(figsize=(10, 6))
sns.heatmap(heatmap_df, annot=True, fmt='d', cmap='YlOrRd',
linewidths=0.5, cbar_kws={'label': '销售额(万元)'})
plt.title('各地区月度销售额热力图', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
# ========== 7. 箱线图:各品类销售额分布 ==========
plt.figure(figsize=(10, 6))
sns.boxplot(x='品类', y='销售额', data=df, palette='Set2')
plt.title('各品类销售额分布(箱线图)', fontsize=14, fontweight='bold')
plt.ylabel('销售额(元)')
plt.tight_layout()
plt.show()
# ========== 8. pandas 内置 plot 快速绘图 ==========
print("\n【pandas 快速绘图示例】")
# 折线图
df_ts = pd.DataFrame({'月份': months, '销售额': sales, '利润': profit})
df_ts.set_index('月份')['销售额'].plot(kind='line', marker='o', title='pandas快速折线图')
plt.show()
# 柱状图
df_ts.set_index('月份')['销售额'].plot(kind='bar', color='#2563eb', title='pandas快速柱状图')
plt.show()
# ========== 9. 组合图:柱状图 + 折线图 ==========
fig, ax1 = plt.subplots(figsize=(10, 5))
ax1.bar(months, sales, color='#2563eb', alpha=0.7, label='销售额')
ax1.set_ylabel('销售额(万元)', color='#2563eb')
ax2 = ax1.twinx()
ax2.plot(months, [s/p*100 for s, p in zip(sales, profit)],
color='#ef4444', marker='o', linewidth=2, label='利润率(%)')
ax2.set_ylabel('利润率(%)', color='#ef4444')
plt.title('销售额与利润率组合图', fontsize=14, fontweight='bold')
fig.legend(loc='upper left')
plt.tight_layout()
plt.show()