完全沒碰過層析數據分析也能跟著走完。我們用一批真實的食品防腐劑檢驗資料, 從「怎麼看懂一張圖」開始,一路做到「算出樣品裡有多少苯甲酸和己二烯酸」。 不需要先懂統計或程式,需要打的指令一共只有三行。
HPLC(高效液相層析)做的事情很單純:把混合樣品打進一根管柱, 不同的成分會用不同的速度通過管柱,於是先後流出來。 出口有一個偵測器,把「每個時刻流出來多少東西」記錄成一條曲線——這就是層析圖。
這批資料裡有兩個目標物,它們是食品最常見的兩種防腐劑:
| 代號 | 中文名 | 英文名 | 大約在第幾分鐘出來 |
|---|---|---|---|
| BA | 苯甲酸 | Benzoic acid | 5.38 分 |
| SA | 己二烯酸(己二烯酸) | Sorbic acid | 5.94 分 |
偵測器只會給你「面積」這個數字,它不知道濃度。 那怎麼把面積換成濃度?答案是先拿已知濃度的樣品去問。
我們配了 5 瓶標準品——濃度分別是 0.25、10、25、50、100 ppm,每瓶都跑一次 HPLC。 把「濃度」和「量到的面積」畫成一張圖,會得到一條直線。 這條線就是檢量線,之後任何未知樣品只要量出面積,就能反過來讀出濃度。
ppm = parts per million,百萬分之一。對液體樣品,1 ppm 就是 1 毫克溶在 1 公升裡(mg/L)。 本文所有濃度都是注射液的濃度;如果要換算成食品本身的含量(mg/kg), 還要乘上前處理時的稀釋倍數。
好消息是:儀器軟體 LCsolution 匯出的檔案裡,已經幫你算好每個峰的面積了。 所以第一版分析只要把這些面積讀出來、配一條線就好。
D:\claude\BASA_hplc 裡有 11 個資料檔(5 個標準品 + 6 個樣品)。python hplc_calib.py
幾秒後 results/ 資料夾就會出現檢量線圖、報表 CSV,畫面上也會印出結果。
你得到的檢量線是:
| 物質 | 檢量線公式 | R² | 報告下限 |
|---|---|---|---|
| BA 苯甲酸 | Area = 83,065.9 x C + 17,648.3 | 0.99685 | 0.25 ppm |
| SA 己二烯酸 | Area = 56,482.7 x C + 31.4 | 0.99749 | 0.25 ppm |
公式裡的 Area 是峰面積、C 是濃度。
要反推濃度就是把公式倒過來:濃度 =(面積 − 截距)÷ 斜率。
用上面真實的檢量線。輸入一個峰面積,看看會得到多少 ppm。
如果事情這麼簡單就好了。實際看資料時會發現一個麻煩: 同一個物質,在不同時間跑出來的圖上,出現的時間不完全一樣。
這批資料裡,sample-1 到 sample-3 是上午跑的,標準品是下午跑的, 中間管柱溫度、流動相都有些微變化,結果上午那幾張圖整體往左偏了約 0.09 分鐘。
0.09 分鐘聽起來很小,但儀器是用「時間視窗」來認峰的—— 它會說「5.90 到 6.00 分之間出現的峰就是己二烯酸」。峰偏出這個範圍,儀器就認不出來:
解法就是峰對位(peak alignment):先把每張圖的峰推回共同的時間軸上,再來積分。 就像把幾張沒對齊的照片疊起來之前,先把它們對準一樣。
alignDE 是一個 R 套件,專門做這件事。它的做法可以這樣理解:
安裝一次,之後就只要跑一行:
# 只需要做一次的安裝
Rscript -e "install.packages(c('DEoptim', 'Matrix', 'remotes'))"
Rscript -e "remotes::install_github('Tai-ShengYeh/alignDE')"
# 每次分析都跑這行
Rscript hplc_alignDE.R
跑完會在 results_align/ 得到對位後的完整結果。實際套用的平移量是:
| 層析圖 | 往後推了幾分鐘 | 和標準品的相似度 |
|---|---|---|
| 25ppm.txt | -0.025 | 0.943 → 1.000 |
| 50ppm.txt | +0.008 | 0.996 → 1.000 |
| sample-1.txt | +0.083 | 0.508 → 0.870 |
| sample-2.txt | +0.100 | 0.199 → 0.522 |
| sample-3.txt | +0.100 | 0.356 → 0.822 |
| sample-4.txt | +0.017 | 0.963 → 0.989 |
| sample-5.txt | -0.008 | 0.814 → 0.821 |
| sample-6.txt | +0.017 | 0.809 → 0.828 |
(沒有列出的檔案表示不需要平移。)
跑出數字很容易,難的是知道這些數字能不能信。看三個地方就好。
把標準品自己的面積代回檢量線,看能不能還原成原本的濃度。 0.25 ppm 的標準品應該要算回 0.25 ppm 附近。一般可接受範圍是 85–115%。
低於最低標準品濃度(本例 0.25 ppm)的結果,不應該直接報數字,要寫 N.D.(未檢出)。 因為那個範圍根本沒有用標準品校正過,數字是外推出來的,不可信。
本專案刻意做了兩套獨立流程:一套直接用儀器算好的面積,一套自己從原始訊號重新積分。 兩套算出來的濃度如果接近,就有信心;差很多的地方就要人工看一下。
| 樣品 | BA 苯甲酸 (ppm) | SA 己二烯酸 (ppm) |
|---|---|---|
| sample-1.txt | 19.40 | 43.81 |
| sample-2.txt | N.D. | 6.02 |
| sample-3.txt | 8.29 | N.D. |
| sample-4.txt | 1.41 | 2.11 |
| sample-5.txt | 10.36 | N.D. |
| sample-6.txt | 31.18 | 0.87 |
N.D. = 未檢出(低於報告下限 0.25 ppm)。
本例的標準品從 0.25 到 100 ppm,跨了 400 倍。 如果用最普通的「最小平方法」配一條線,這條線會被 100 ppm 那個點整個拉過去, 低濃度端完全失準:
解法叫做加權:讓低濃度的點在配線時擁有比較大的發言權。 標準做法是給每個點 1/C² 的權重(C 是該點濃度)。本專案的程式已經預設這樣做了, 你只要知道:濃度範圍超過大約 50 倍時,一定要加權。
「未檢出」的意思是低於偵測能力,不是確定沒有。報告時應該寫 「N.D.(< 0.25 ppm)」,而不是 0。
峰越小,基線畫在哪裡對面積的影響就越大。本專案比較過兩種基線演算法, 主要的峰結果差異都在 2% 以內,但接近報告下限的微量峰可以差到 50%。 接近下限的數字,一定要人工看過原始圖。
四題,點選答案會立刻告訴你對不對。
這裡是第 1 站。接下來還有兩站,照順序讀最順:
| 檔案 | 用途 |
|---|---|
hplc_calib.py / .R | 流程 A:直接用儀器算好的面積建檢量線 |
hplc_alignDE.R | 流程 B:自己做對位與積分 |
make_beginner_figs.py | 產生這份文件的圖 |
build_beginner_html.py | 產生這份文件 |
README.md | 完整技術說明與參考文獻 |