4. 物理化学属性数据:LogP、溶解度、pKa 的收集与单位统一

好,咱们接着聊。前面讲了理化性质数据怎么筛选和编号,这一步其实只是开了个头。拿到一堆 LogP、溶解度、pKa 数据后,你会发现一个很头疼的问题——单位不统一,甚至概念本身都可能有歧义。我刚开始做 ADMET 建模那会儿,就被这些细节坑过不少次。

4.1 为什么是这三个参数?

先说个基本的。LogP、溶解度、pKa 是药物理化性质的三驾马车,大部分口服吸收预测模型都离不开它们。但问题是,这三个玩意儿测量方法多、数据来源杂,质控起来特别麻烦。

  • LogP:反映脂溶性,直接影响膜透过性。但你会看到 LogP、LogD、clogP 混在一起。
  • 溶解度:光 pH 条件就有七八种。有的给 µg/mL,有的给 mg/mL,还有直接给摩尔浓度的。
  • pKa:看起来简单,就是酸解离常数。可多价化合物在不同文献里能给出差 2 个单位的数,你信不?

它们之间的关系其实很紧密。我画了张图,你可以先看一眼,这样后续讲细节时心里有个谱。

物理化学属性质控流程 原始数据收集 LogP / LogD / clogP 溶解度(多种 pH) pKa(多价态) 质控检查:单位统一 + 数据源校验 单位换算表 规范归一化 异常值剔除 标准化数据仓库

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 用了。说白了,一个是没解离的状态,一个是部分解离的状态,怎么能直接混呢?

注意: 如果数据库中混用了 LogP 和 LogD,建模结果不可靠。建议先统一标注“数据来源”。对于计算值,最好统一到同一个计算器,比如 RDKit 的 MolLogP。

4.3 溶解度:单位是最大陷阱

溶解度这块,数据源常见的单位大概有这么几种:

  • mg/mL (最常见的质量浓度)
  • µg/mL (微克每毫升,低溶常用)
  • mol/L 或 M (摩尔浓度,学术文献爱用)
  • µM (微摩尔每升)
  • 甚至还有 g/100mL 这种老古董

你想想看,如果不统一单位,直接用原始值建模,那模型学到的全是单位差异,根本不是物理化学规律。

统一换算的方法其实挺简单。核心公式就一个:

溶解度 (mol/L) = 溶解度 (mg/mL) / 分子量 (g/mol) * 1000

反过来换算也一样。嗯,这里要注意:分子量必须用精确分子量(exact mass),不要用平均分子量。差那么零点几,对后续 ADMET 模型影响不大,但严谨性上过不去。

我自己的流程是:

  1. 把所有溶解度数值先转成 µM。
  2. 记录原始单位和转换公式。
  3. 如果同一化合物的多个文献数据差距 > 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 单位统一的实操流程

好,理论讲完了,说说具体怎么干。我建议的数据清洗步骤大概是这样的:

  1. 原始数据分拆:把 LogP、溶解度、pKa 分开处理。
  2. 字段追加:为每个数据增加两个字段——“原始值”和“标准值”。不要覆盖原始值。
  3. 单位统一:对溶解度,全部转换为 µM。对 LogP,标注是 LogP 还是 LogD。对 pKa,保留多位有效数字。
  4. 异常检查:超出合理范围的数值直接标记。
  5. 入库:标准化后的数据存入主表。

这块的代码,我一般这么写(粗暴但有效):

# 溶解度统一转换函数
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,然后程序报错,全流程断掉。建议提前写异常处理。

我在项目中,曾建立过一个内部数据标准规范表,里面就列出了这三种属性允许的单位、转换公式、以及合理范围。用了几个月后,出问题的频率降低了不少。

最后总结一句:物理化学属性数据的单位统一,说白了就是让不同源的数据能在同一把尺子上说话。你做得好,后面的模型就能少踩很多坑。