4. 物理化学属性数据:LogP、溶解度、pKa 的收集与单位统一
好,咱们接着聊。前面讲了理化性质数据怎么筛选和编号,这一步其实只是开了个头。拿到一堆 LogP、溶解度、pKa 数据后,你会发现一个很头疼的问题——单位不统一,甚至概念本身都可能有歧义。我刚开始做 ADMET 建模那会儿,就被这些细节坑过不少次。
4.1 为什么是这三个参数?
先说个基本的。LogP、溶解度、pKa 是药物理化性质的三驾马车,大部分口服吸收预测模型都离不开它们。但问题是,这三个玩意儿测量方法多、数据来源杂,质控起来特别麻烦。
- LogP:反映脂溶性,直接影响膜透过性。但你会看到
LogP、LogD、clogP混在一起。 - 溶解度:光 pH 条件就有七八种。有的给
µg/mL,有的给mg/mL,还有直接给摩尔浓度的。 - pKa:看起来简单,就是酸解离常数。可多价化合物在不同文献里能给出差 2 个单位的数,你信不?
它们之间的关系其实很紧密。我画了张图,你可以先看一眼,这样后续讲细节时心里有个谱。
4.2 LogP:三个容易混淆的兄弟
LogP 这块儿,单位倒没什么大变化,就是数值。但概念上的坑特别多。我整理了个表,你对照着看:
| 符号 | 全称 | pH 条件 | 典型用途 |
|---|---|---|---|
LogP |
油水分配系数 (octanol/water) | 中性 (未解离) | 评价固有脂溶性 |
LogD |
分布系数 (Distribution coefficient) | 指定 pH (如 7.4) | 模拟生理环境 |
clogP |
计算 LogP (Calculated LogP) | 无 (算法估算) | 高通量筛选 |
我个人习惯首先问一句话:“数据集里这个 LogP 是测的还是算的?” 如果是计算的,注明软件版本。如果是测量的,一定要看 pH。
我在项目中遇到过,有个合作方给的 LogP 数据,拿去建模型,结果预测吸收率和实测总是差 20%。查来查去,发现他们拿最常给的 7.4 的 LogD 当 LogP 用了。说白了,一个是没解离的状态,一个是部分解离的状态,怎么能直接混呢?
RDKit 的 MolLogP。
4.3 溶解度:单位是最大陷阱
溶解度这块,数据源常见的单位大概有这么几种:
mg/mL(最常见的质量浓度)µg/mL(微克每毫升,低溶常用)mol/L或M(摩尔浓度,学术文献爱用)µM(微摩尔每升)- 甚至还有
g/100mL这种老古董
你想想看,如果不统一单位,直接用原始值建模,那模型学到的全是单位差异,根本不是物理化学规律。
统一换算的方法其实挺简单。核心公式就一个:
溶解度 (mol/L) = 溶解度 (mg/mL) / 分子量 (g/mol) * 1000
反过来换算也一样。嗯,这里要注意:分子量必须用精确分子量(exact mass),不要用平均分子量。差那么零点几,对后续 ADMET 模型影响不大,但严谨性上过不去。
我自己的流程是:
- 把所有溶解度数值先转成
µM。 - 记录原始单位和转换公式。
- 如果同一化合物的多个文献数据差距 > 10 倍,标记为可疑。
convert_solubility() 函数,把几种常见单位一次性转好。我在项目中用过一个函数,输入原始值和单位,输出标准 µM 值和分子量检查 flag。
另外,溶解度和 pH 的关系特别密切。大部分有价值的数据都附带 pH 条件,比如 1.2(模拟胃液)、6.8(模拟肠液)或 7.4(血液)。如果没写 pH,默认当成“纯水中的溶解度”。
4.4 pKa:多价态的复杂问题
pKa 说起来是原子级别的数据,通常是用滴定法测的。但麻烦的地方在于:
- 一个分子可能有多个 pKa(比如阿司匹林有两个可解离基团)
- 不同基团的 pKa 会有交叉影响
- 实验条件不同(温度、离子强度),pKa 能差 0.5 个数量级
我遇到过一个真实案例。有份数据里记录“pKa=4.5”,结果查文献发现,这个化合物其实有两个等价的羧基,实际测出来的是两个相近 pKa 的平均值。这种数据如果直接使用,会严重影响后面模型的电荷状态预测。
我的经验是:多酸多碱基团的化合物,最好列个表,把所有 pKa 值都记录下来。不要只记一个“主要 pKa”。
pKa1: 4.2 (羧基), pKa2: 9.8 (铵基),并注明测量时的温度和离子强度。
4.5 单位统一的实操流程
好,理论讲完了,说说具体怎么干。我建议的数据清洗步骤大概是这样的:
- 原始数据分拆:把 LogP、溶解度、pKa 分开处理。
- 字段追加:为每个数据增加两个字段——“原始值”和“标准值”。不要覆盖原始值。
- 单位统一:对溶解度,全部转换为
µM。对 LogP,标注是LogP还是LogD。对 pKa,保留多位有效数字。 - 异常检查:超出合理范围的数值直接标记。
- 入库:标准化后的数据存入主表。
这块的代码,我一般这么写(粗暴但有效):
# 溶解度统一转换函数
def unify_solubility(value, unit, molecular_weight):
if unit == 'mg/mL':
return (value / molecular_weight) * 1e3 # µM
elif unit == 'µg/mL':
return (value / 1e3 / molecular_weight) * 1e3
elif unit == 'M':
return value * 1e6
elif unit == 'µM':
return value
else:
raise ValueError("未知单位: {}".format(unit))
注意,这个函数只做单位转换,不做数据合理性判断。合理的判断要单独做,比如 value < 0、value > 1e5 这类情况要 flag 出来。
float 类型的除法而不考虑分子量。我见过有的数据库把分子量写成 None,然后程序报错,全流程断掉。建议提前写异常处理。
我在项目中,曾建立过一个内部数据标准规范表,里面就列出了这三种属性允许的单位、转换公式、以及合理范围。用了几个月后,出问题的频率降低了不少。
最后总结一句:物理化学属性数据的单位统一,说白了就是让不同源的数据能在同一把尺子上说话。你做得好,后面的模型就能少踩很多坑。