从零开始的数据分析之旅
Matplotlib是Python最基础也最重要的可视化库,几乎所有高级绘图库(Seaborn、Plotly等)都构建在它之上。掌握Matplotlib,你就能绘制任何想要的图表,并拥有完全的控制力。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2*np.pi, 100)
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x, np.sin(x), 'b-', label='sin(x)', linewidth=2)
ax.plot(x, np.cos(x), 'r--', label='cos(x)', linewidth=2)
ax.set_title('折线图: sin & cos')
ax.legend()
ax.grid(True, alpha=0.3)
plt.savefig('line_chart.png', dpi=150, bbox_inches='tight')
| 图表 | 适用场景 | 核心函数 | 数据类型 |
|---|---|---|---|
| 折线图 | 趋势/变化 | ax.plot() | 时间序列/连续 |
| 柱状图 | 比较/排名 | ax.bar() | 分类/离散 |
| 散点图 | 关系/分布 | ax.scatter() | 两个连续变量 |
| 饼图 | 占比/构成 | ax.pie() | 比例数据 |
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 78]
colors = ['#3b82f6', '#60a5fa', '#93c5fd', '#bfdbfe']
ax.bar(categories, values, color=colors, edgecolor='white')
for i, v in enumerate(values):
ax.text(i, v+1, str(v), ha='center') # 数据标签
np.random.seed(42)
sx = np.random.randn(50)
sy = np.random.randn(50)
ax.scatter(sx, sy, c=np.abs(sx), cmap='coolwarm', s=100,
alpha=0.7, edgecolors='white')
labels = ['Python', 'R', 'SQL', 'Java', '其他']
sizes = [35, 20, 25, 12, 8]
explode = (0.05, 0, 0, 0, 0)
ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%')
# 2×2子图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes[0,0].plot(...) # 左上
axes[0,1].bar(...) # 右上
axes[1,0].scatter(...) # 左下
axes[1,1].pie(...) # 右下
# 不规则布局
fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212) # 占满底部
plt.style.use('dark_background')
# 或手动设置
plt.rcParams.update({
'figure.facecolor': '#0f0f1a',
'axes.facecolor': '#1a1a2e',
'text.color': '#e0e0e0',
'axes.labelcolor': '#e0e0e0',
})
bbox_inches='tight'避免标签被截断,用dpi=150+保证清晰度。# 自定义调色板
blue_palette = ['#0f172a','#1e40af','#3b82f6','#60a5fa','#93c5fd']
# 注释与标注
ax.annotate('最大值',
xy=(np.pi/2, 1),
xytext=(2, 0.8),
arrowprops=dict(arrowstyle='->', color='#60a5fa', lw=2),
fontsize=12, color='#60a5fa')
# 文本框
ax.text(0.5, -0.5, 'y = sin(x)', fontsize=14,
bbox=dict(boxstyle='round', facecolor='#1a1a2e',
edgecolor='#3b82f6', alpha=0.8),
color='#e0e0e0')
# 堆叠柱状图
ax.bar(categories, product_a, label='A', color='#3b82f6')
ax.bar(categories, product_b, bottom=product_a, label='B', color='#60a5fa')
# 水平柱状图
ax.barh(categories, values, color='#3b82f6')
# 面积图
ax.fill_between(x, np.sin(x), alpha=0.3, color='#3b82f6')
# 热力图(Matplotlib版)
data = np.random.randn(10, 10)
im = ax.imshow(data, cmap='coolwarm', aspect='auto')
plt.colorbar(im, ax=ax)
#!/usr/bin/env python3
# Matplotlib — 完整实战
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
# ============ 折线图 ============
x = np.linspace(0, 2*np.pi, 100)
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes[0,0].plot(x, np.sin(x), 'b-', label='sin(x)', linewidth=2)
axes[0,0].plot(x, np.cos(x), 'r--', label='cos(x)', linewidth=2)
axes[0,0].set_title('折线图: sin & cos')
axes[0,0].legend()
axes[0,0].grid(True, alpha=0.3)
# ============ 柱状图 ============
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 78]
colors = ['#3b82f6', '#60a5fa', '#93c5fd', '#bfdbfe']
axes[0,1].bar(categories, values, color=colors, edgecolor='white')
axes[0,1].set_title('柱状图')
for i, v in enumerate(values):
axes[0,1].text(i, v+1, str(v), ha='center')
# ============ 散点图 ============
np.random.seed(42)
sx = np.random.randn(50)
sy = np.random.randn(50)
axes[1,0].scatter(sx, sy, c=np.abs(sx), cmap='coolwarm', s=100, alpha=0.7, edgecolors='white')
axes[1,0].set_title('散点图')
axes[1,0].grid(True, alpha=0.3)
# ============ 饼图 ============
labels = ['Python', 'R', 'SQL', 'Java', '其他']
sizes = [35, 20, 25, 12, 8]
explode = (0.05, 0, 0, 0, 0)
axes[1,1].pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
colors=['#3b82f6','#60a5fa','#93c5fd','#bfdbfe','#dbeafe'])
axes[1,1].set_title('饼图')
plt.tight_layout()
plt.savefig('charts.png', dpi=100, bbox_inches='tight')
print("图表已保存")
# ============ 深色主题 ============
plt.style.use('dark_background')
fig2, ax = plt.subplots(figsize=(8, 4))
ax.plot(np.cumsum(np.random.randn(100)), color='#3b82f6', linewidth=1.5)
ax.set_title('随机游走')
ax.grid(True, alpha=0.2)
plt.savefig('dark.png', dpi=100, bbox_inches='tight')
print("深色主题图表已保存")
print("\n✅ Python验证通过 — 折线/柱状/散点/饼图")
| 用途 | 格式 | DPI | 尺寸 |
|---|---|---|---|
| 网页显示 | PNG | 100-150 | 10×6英寸 |
| 论文投稿 | PDF/EPS | 300+ | 期刊要求 |
| PPT演示 | PNG | 150-200 | 12×8英寸 |
| 打印海报 | PNG/TIFF | 300+ | 实际尺寸 |
| 交互网页 | SVG | 矢量 | 自适应 |
bbox_inches='tight'避免截断,dpi=150+保证清晰plt.style.use('dark_background')plt.subplots(行, 列)创建
# Matplotlib速查
fig, ax = plt.subplots(figsize=(10, 6))
# 四大图表
ax.plot(x, y) # 折线
ax.bar(categories, values) # 柱状
ax.scatter(x, y) # 散点
ax.pie(sizes, labels=labs) # 饼图
# 美化
ax.set_title('标题')
ax.set_xlabel('X轴')
ax.legend()
ax.grid(True, alpha=0.3)
# 保存
plt.savefig('fig.png', dpi=150, bbox_inches='tight')
alpha避免过度绘制 ②十万级数据点用rasterized=True ③百万级考虑Datashader ④保存PDF时矢量图可能很大,用dpi控制。plt.rcParams['font.sans-serif']=['SimHei'] ②保存时标签被截断——加bbox_inches='tight' ③子图标题重叠——plt.tight_layout() ④颜色循环不够——自定义color列表。