第2章:光谱数据加载与可视化
各位好,欢迎来到光谱数据清洗的第一站。说实话,很多新手拿到光谱数据后,第一件事就是急着建模、找差异。我个人的建议是——先别急,先看看你的数据长什么样。
这一章,我们就来聊聊怎么把光谱数据读进来,再画出来。你想想看,数据都没看清楚,你怎么知道它有没有问题?
2.1 光谱数据的常见格式
在实际项目中,我遇到过至少十几种不同的光谱数据格式。但最常见的,无非这三种:
| 格式 | 特点 | 常见来源 |
|---|---|---|
| CSV | 纯文本,逗号或制表符分隔 | 通用、实验室自建系统 |
| SPA | Thermo Scientific 专用二进制格式 | Nicolet 系列红外光谱仪 |
| ASCII | 纯文本,通常两列(波数、吸光度) | 老旧仪器、第三方软件导出 |
嗯,这里要注意:SPA 格式是二进制文件,不能直接用记事本打开。我曾经有个同事,拿记事本打开 SPA 文件,看到一堆乱码,还以为仪器坏了……
2.2 用 Python 读取光谱数据
我个人习惯用 pandas 处理 CSV 和 ASCII,用 pySPA 处理 SPA 格式。下面给出三种格式的读取示例。
2.2.1 读取 CSV 格式
import pandas as pd
# 假设 CSV 文件有两列:Wavenumber, Absorbance
df = pd.read_csv('sample_spectrum.csv')
wavenumber = df['Wavenumber'].values
absorbance = df['Absorbance'].values
这里有个小坑:有些 CSV 文件第一行不是列名,而是仪器信息。记得加 skiprows=1 跳过它。
2.2.2 读取 ASCII 格式
import numpy as np
# ASCII 文件通常用空格或制表符分隔
data = np.loadtxt('sample_spectrum.txt')
wavenumber = data[:, 0]
absorbance = data[:, 1]
为什么用 np.loadtxt 而不是 pd.read_csv?说白了,ASCII 文件往往没有表头,用 NumPy 更直接。
2.2.3 读取 SPA 格式
# 需要安装 pySPA: pip install pyspa
from pyspa import SPAFile
spa = SPAFile('sample_spectrum.spa')
wavenumber = spa.x
absorbance = spa.y
2.3 绘制原始光谱图
数据读进来了,下一步就是画图。我用 Matplotlib 画了十几年光谱图,有些习惯一直没变。
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))
plt.plot(wavenumber, absorbance, color='steelblue', linewidth=0.8)
plt.xlabel('Wavenumber (cm⁻¹)')
plt.ylabel('Absorbance')
plt.title('Raw Spectrum - Sample #001')
plt.gca().invert_xaxis() # 波数通常从高到低显示
plt.tight_layout()
plt.show()
注意最后一行 invert_xaxis()。光谱图的横坐标习惯从高波数到低波数,也就是 4000 在左边,400 在右边。我第一次画图时忘了这步,被导师说了一顿。
2.4 初步观察数据质量
画完图,别急着关。盯着图看 10 秒钟,你能发现很多信息。
2.4.1 看基线
基线平不平?有没有整体漂移?我见过最夸张的一次,基线从 0 漂到了 0.5,原因是样品池没洗干净。
2.4.2 看噪声
光谱曲线是不是毛刺很多?尤其在 2000-2500 cm⁻¹ 区域,如果噪声明显,说明仪器状态可能不太好。
2.4.3 看异常峰
有没有不该出现的峰?比如水汽峰(~1640 cm⁻¹ 和 ~3400 cm⁻¹)或者 CO₂ 峰(~2350 cm⁻¹)。
2.5 本章知识体系
下面这张图,是我自己总结的光谱数据加载与可视化的核心逻辑。你跟着这个流程走,基本不会漏掉关键步骤。
这张图其实就说了三件事:读进来、画出来、看一眼。别小看这「看一眼」,它能帮你省掉后面 80% 的排查时间。
- 不同格式用不同工具,别硬来
- 画图时记得反转波数轴
- 观察基线、噪声、异常峰,这是数据清洗的第一步
好了,这一章就到这里。数据加载和可视化是基本功,练熟了后面才能走得顺。下一章我们聊聊光谱去噪,那又是一个有意思的话题。
公众号:蓝海资料掘金营,微信deep3321