Matplotlib入门:用图表让数字说话
Matplotlib入门:用图表让数字说话
一、问题背景:30页表格,老板看了5分钟说"听不懂"
这是我踩过的坑。
上个月做月度质量汇报,准备了30页数据表格——每个Lot的厚度均值、标准差、Cpk、缺陷数,列得清清楚楚。
结果老板翻了两页说:"你能不能直接说结论?这个月到底怎么样?"
我说数据在里面,你看一下就知道了。
老板说:"我没时间看数据,你给我画个图。"
之后我花了两天时间画图,第二次汇报5分钟就结束了。 老板看到控制图直接说:"这个月第13批有问题,马上查原因。"
这就是可视化——把数据变成图,图变成了结论。
学完这一篇,你能做到:
1. 画折线图看趋势(良率走势、厚度变化)
2. 画柱状图做对比(各工序良率排名)
3. 画散点图找关系(缺陷数和良率的关系)
4. 画直方图看分布(厚度数据的分布规律)
---
二、技术原理:一张图的4个要素
```python
import matplotlib.pyplot as plt
折线图——最基础的图
x = [1, 2, 3, 4, 5]
y = [1250, 1248, 1251, 1249, 1250]
plt.plot(x, y, 'o-', color='blue', linewidth=2)
plt.title('膜厚趋势')
plt.xlabel('批次')
plt.ylabel('厚度 (Å)')
plt.grid(True) # 加网格线
plt.show()
```
一张图只要有:标题、X轴标签、Y轴标签、数据,别人就能看懂了。其他装饰都是锦上添花。
最常用的4种图
```python
import matplotlib.pyplot as plt
import numpy as np
1. 折线图(看趋势)
x = [1, 2, 3, 4, 5]
y = [96.5, 95.8, 97.2, 94.5, 96.1]
plt.figure(figsize=(8, 4))
plt.plot(x, y, 'o-', label='良率')
plt.axhline(y=95, color='red', linestyle='--', label='警戒线')
plt.title('良率趋势'); plt.xlabel('批次'); plt.ylabel('良率(%)')
plt.legend(); plt.grid(True)
plt.show()
2. 柱状图(做对比)
processes = ['ETCH', 'CVD', 'PHOTO', 'CMP']
yields = [96.2, 95.1, 97.5, 94.8]
plt.figure(figsize=(8, 4))
plt.bar(processes, yields, color=['blue', 'green', 'orange', 'red'])
plt.title('各工序平均良率'); plt.ylabel('良率(%)')
plt.show()
3. 散点图(找关系)
defects = np.random.poisson(8, 100) # 缺陷数
yields = 98 - defects 0.3 + np.random.randn(100) 2 # 对应良率
plt.figure(figsize=(8, 4))
plt.scatter(defects, yields, alpha=0.6)
plt.title('缺陷数 vs 良率'); plt.xlabel('缺陷数'); plt.ylabel('良率(%)')
plt.show()
4. 直方图(看分布)
data = np.random.normal(1250, 3, 500) # 500个膜厚数据
plt.figure(figsize=(8, 4))
plt.hist(data, bins=20, color='skyblue', edgecolor='black')
plt.axvline(x=1247, color='red', linestyle='--', label='规格下限')
plt.axvline(x=1253, color='red', linestyle='--', label='规格上限')
plt.title('膜厚分布'); plt.xlabel('厚度 (Å)'); plt.ylabel('频次')
plt.legend()
plt.show()
```
---
三、实战案例:FAB数据可视化
3.1 控制图(折线图+控制线)
```python
import numpy as np
import matplotlib.pyplot as plt
模拟数据
np.random.seed(42)
thickness = np.random.normal(1250, 3, 100)
统计量
mean = np.mean(thickness)
ucl = mean + 3 * np.std(thickness)
lcl = mean - 3 * np.std(thickness)
画图
plt.figure(figsize=(12, 5))
plt.plot(range(1, 101), thickness, 'o-', markersize=3, color='#1976D2')
plt.axhline(ucl, color='red', linestyle='--', label=f'UCL={ucl:.1f}')
plt.axhline(mean, color='green', linewidth=2, label=f'均值={mean:.1f}')
plt.axhline(lcl, color='red', linestyle='--', label=f'LCL={lcl:.1f}')
标出异常点
anomaly = np.where((thickness > ucl) | (thickness < lcl))[0]
plt.scatter(anomaly + 1, thickness[anomaly], color='red', s=50, zorder=5)
plt.title('膜厚控制图', fontsize=14)
plt.xlabel('样本序号'); plt.ylabel('厚度 (Å)')
plt.legend(); plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
```
3.2 工序对比(柱状图)
```python
各工序数据
pro_data = {
'ETCH': {'yield': 96.2, 'defects': 5.3, 'lots': 120},
'CVD': {'yield': 95.1, 'defects': 7.8, 'lots': 95},
'PHOTO':{'yield': 97.5, 'defects': 3.2, 'lots': 80},
'CMP': {'yield': 94.8, 'defects': 9.1, 'lots': 110},
}
pro_names = list(pro_data.keys())
yield_vals = [pro_data[p]['yield'] for p in pro_names]
设置颜色:低于95%标红
colors = ['red' if y < 95 else 'steelblue' for y in yield_vals]
plt.figure(figsize=(8, 5))
bars = plt.bar(pro_names, yield_vals, color=colors)
在柱子上标数值
for bar, val in zip(bars, yield_vals):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.2,
f'{val}%', ha='center', fontsize=12)
plt.axhline(y=95, color='red', linestyle='--', label='目标95%')
plt.title('各工序良率对比', fontsize=14)
plt.ylabel('良率(%)')
plt.ylim(90, 100)
plt.legend(); plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()
```
3.3 良率和缺陷的关系(散点图+趋势线)
```python
模拟500批的数据
np.random.seed(42)
n = 500
defects = np.random.poisson(8, n)
yield_pct = 98 - defects 0.4 + np.random.randn(n) 2.5
yield_pct = np.clip(yield_pct, 80, 100) # 限制在合理范围
plt.figure(figsize=(10, 5))
散点
plt.scatter(defects, yield_pct, alpha=0.4, s=20, color='#1976D2')
拟合趋势线
z = np.polyfit(defects, yield_pct, 1)
p = np.poly1d(z)
x_line = np.linspace(defects.min(), defects.max(), 100)
plt.plot(x_line, p(x_line), 'r--', linewidth=2,
label=f'y = {z[0]:.2f}x + {z[1]:.2f}')
plt.title('缺陷数 vs 良率', fontsize=14)
plt.xlabel('缺陷数 (个)'); plt.ylabel('良率 (%)')
plt.legend(); plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
print(f"相关系数: {np.corrcoef(defects, yield_pct)[0,1]:.3f}")
```
---
四、效果对比
| 呈现方式 | 老板看完做决策 | 工程师发现问题 | 新人理解数据 |
|---------|--------------|--------------|------------|
| 30页数据表格 | 5分钟看不懂 | 2小时分析 | 完全懵 |
| 3张图表 | 30秒出结论 | 5分钟定位问题 | 一目了然 |
核心道理:你花2小时分析的结论,让别人10秒看懂,这就是可视化的价值。
---
五、自己动手
```python
练习:画你自己的数据
import matplotlib.pyplot as plt
import numpy as np
模拟你的一周生产数据
days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
yields = [95.2, 96.1, 94.5, 93.8, 97.0, 96.5, 95.8]
练习1:画折线图,标注低于95%的点
练习2:改成柱状图,把不合格的柱子标红
练习3:加一条95%的警戒线
✏️ 下面写你的代码
```
思考题:
1. 什么时候该用折线图,什么时候用柱状图?(趋势用折线,对比用柱状)
2. 散点图里的异常点怎么标出来?试试用不同颜色区分
3. 如果数据很多(比如1万个点),散点图全是黑点看不清怎么办?(提示:设置 `alpha=0.3` 透明度)
---
六、常见误区
| 问题 | 表现 | 解决 |
|------|------|------|
| 中文乱码 | □□□ | `plt.rcParams['font.sans-serif']=['SimHei']` |
| 图太多看不清 | 数据点叠在一起 | 设置 `alpha=0.3` 透明度 |
| 坐标轴没标注 | 看图不知道X轴是啥 | 永远加 `xlabel` 和 `ylabel` |
| 颜色太花哨 | 像烟花一样 | 一篇图不超过3种颜色 |
| 图例放哪里 | 挡住数据了 | `loc='upper left'` 或 `'best'` |
---
> 💬 你有"被老板说图看不懂"的经历吗?评论区聊聊
> 📚 收藏+点赞,下一篇讲解bug和测试 👆





