ADMET 数据预处理:缺失值处理与标准化
拿到 ADMET 原始数据,第一件事别急着跑模型。我见过太多人上来就调包,结果模型跑完才发现数据里一堆 NaN,或者量级差了一千倍。说白了,数据预处理决定了下限,ComBat 校正再厉害,也填不了缺失的坑。这一章我们就专门聊怎么把数据收拾干净。
先看看数据长什么样
假设你已经从实验或公开数据库拿到了 ADMET 数据,通常是一个矩阵:行是化合物,列是不同 ADMET 指标(比如 LogD、溶解度、Caco‑2 渗透性、血浆蛋白结合率……)。批次信息藏在另一列里。我习惯第一步就用 pandas 扫一眼统计摘要:
import pandas as pd
df = pd.read_csv("admet_raw.csv")
print(df.info())
print(df.describe())
从 info() 里你能立马看出每列有多少非空值。如果某列缺失超过一半,嗯,这列要不要保留就得琢磨一下了。我个人经验是,超过 60% 缺失的指标,校正后也不可信,干脆删掉。
缺失值处理:三种常用思路
缺失值处理没有银弹。你想想看,ADMET 数据往往是少量化合物、多指标,随便删行可能损失宝贵样本。我这里整理了一个表格,帮你对号入座:
| 缺失场景 | 推荐方法 | 注意事项 |
|---|---|---|
| 随机缺失(总体 < 5%) | 直接删除该行 | 样本量充足时可用 |
| 某指标缺失较多(10% - 30%) | 简单插补(均值/中位数/众数) | 需按批次分组插补,避免引入批次偏差 |
| 缺失有规律(比如某批次全部缺失) | 模型插补(KNN / 回归) | 交叉验证评估插补质量 |
实战:按批次分组插补
下面这段代码演示了按批次分组,用中位数填充缺失值。注意我保留了一个标记列,方便后续追踪哪些值被插补过:
df["missing_flag"] = 0
for batch in df["batch"].unique():
mask = df["batch"] == batch
for col in admet_cols:
median_val = df.loc[mask, col].median()
missing_idx = df.loc[mask & df[col].isna()].index
df.loc[missing_idx, col] = median_val
df.loc[missing_idx, "missing_flag"] = 1
标准化:统一尺度,拯救收敛
ADMET 指标单位五花八门:LogD 在 -2 到 6 之间,溶解度可能是 μg/mL(几十到几千),Caco‑2 渗透性又是 10⁻⁶ cm/s。假如不标准化,ComBat 模型里的迭代过程会被量级大的指标主导,小指标校正不动。
标准化的核心目的是让每个指标近似均值为 0、标准差为 1。我自己更喜欢用 RobustScaler,因为 ADMET 数据常有离群点——有些化合物溶解度特别低或者特别高,Z‑score 会被带跑偏。
三种标准化方法对比
- StandardScaler: (x - μ) / σ — 对离群点敏感
- RobustScaler: (x - Q2) / (Q3 - Q1) — 用中位数和四分位距,抗离群
- MinMaxScaler: (x - min) / (max - min) — 压缩到 [0,1],但离群点会压缩正常值
在 ComBat 校正前,标准化要基于所有批次合并后的统计量来做。为什么?因为我们要保留批次间差异的原始结构,让 ComBat 去识别和校正。如果每个批次单独标准化,等于把批次效应先抹掉了一部分,校正会失真。
代码实现:分指标标准化
from sklearn.preprocessing import RobustScaler
scaler_dict = {}
for col in admet_cols:
scaler = RobustScaler()
# 注意:reshape(-1,1) 是因为 scikit-learn 要求 2D 输入
scaled_values = scaler.fit_transform(df[[col]])
df[col + "_scaled"] = scaled_values
scaler_dict[col] = scaler
# 之后用 _scaled 列做 ComBat 校正
# 校正后可以 inverse_transform 回到原始量纲
代码里我额外保存了每个指标的 scaler 对象,因为校正完你可能想还原回去做结果解读。
本章知识体系
下面这张 SVG 图把预处理流程串起来了:从原始数据出发,先做缺失值处理(分策略),再做标准化(选方法),最后进入 ComBat 校正阶段。
看完这张图你应该能感受到:预处理不是独立步骤,它跟后续校正方法紧密相关。插补不对,标准化方向错,ComBat 校正的结果就很难挽救。
实战中常见问题速查
- 问:缺失值超过 80% 怎么办?
答:直接删除该列。插补 80% 的数据等于编造,不会带来有用信息。 - 问:不同批次缺失模式不一样,能统一插补吗?
答:绝对不能。你想想看,如果批次1缺失了 LogD,批次2没有,统一插补会把批次2的信息“泄露”到批次1,人为缩小批次差异。ComBat 会被误导。 - 问:标准化后是否需要反标准化?
答:ComBat 校正一般不需要反标准化,它直接在标准化后的矩阵上操作。但如果你要输出原始量纲的报告,记得用之前保存的 scaler 做 inverse_transform。