RDKit中聚合物SMILES转特征向量:含‘*C*’结构时出现NaN值求解
问题解决:带通配符的SMILES生成特征向量返回NaN的处理
原因分析
你遇到的问题是因为*在SMILES中是通配符,代表任意未知原子。RDKit的大多数分子描述符(比如分子量、拓扑指数等)依赖明确的原子属性(原子量、价态等),通配符的原子没有这些明确属性,导致部分描述符计算失败,返回NaN或无穷大值。你的computeDescriptors函数会因为检测到非有限值(NaN/inf)而返回None。
另外你的代码里smiles列表存在语法错误,需要修正为合法的Python列表格式。
解决方案
根据你的使用场景,有以下几种处理方式:
1. 替换通配符为具体原子(推荐,若已知端基)
如果你的聚合物重复单元的端基是明确的(比如氢原子),可以将*替换为具体原子,让结构完整,这样所有描述符都能正常计算。
2. 过滤/填充NaN值
保留能正常计算的描述符,对NaN值进行填充(比如用所有样本的均值、中位数,或者0),避免直接返回None。
3. 使用RDKit标准的聚合物连接点表示
RDKit支持用[*]表示聚合物重复单元的连接点,替换*为[*]可以让RDKit更好地识别结构,部分描述符能正常计算。
代码示例
修正基础语法错误
首先修正smiles列表的语法错误:
smiles = ['*C*', 'C1CCCC1', 'CCCCCC', 'CCCC(C)C']
方案1:替换通配符为H原子
import numpy as np from rdkit import Chem from rdkit.Chem import Descriptors from rdkit.ML.Descriptors import MoleculeDescriptors descriptors = [desc[0] for desc in Descriptors._descList] calculator = MoleculeDescriptors.MolecularDescriptorCalculator(descriptors) def computeDescriptors(mol, calculator): res = np.array(calculator.CalcDescriptors(mol)) # 检查是否有非有限值,用均值填充NaN/inf mask = np.isfinite(res) if not np.all(mask): res[~mask] = np.mean(res[mask]) return res # 替换通配符为H processed_smiles = [s.replace('*', 'H') for s in smiles] mol_objects = [Chem.MolFromSmiles(smile) for smile in processed_smiles] features = [computeDescriptors(x, calculator) for x in mol_objects] print(features)
方案2:过滤无法计算的描述符
只保留对通配符结构能正常计算的描述符:
import numpy as np from rdkit import Chem from rdkit.Chem import Descriptors from rdkit.ML.Descriptors import MoleculeDescriptors # 先测试哪些描述符能处理*C*结构 test_mol = Chem.MolFromSmiles('*C*') valid_descriptors = [] for desc_name, _ in Descriptors._descList: try: desc_func = getattr(Descriptors, desc_name) val = desc_func(test_mol) if np.isfinite(val): valid_descriptors.append(desc_name) except: continue # 使用过滤后的描述符计算器 calculator = MoleculeDescriptors.MolecularDescriptorCalculator(valid_descriptors) def computeDescriptors(mol, calculator): return np.array(calculator.CalcDescriptors(mol)) mol_objects = [Chem.MolFromSmiles(smile) for smile in smiles] features = [computeDescriptors(x, calculator) for x in mol_objects] print(f"保留的有效描述符数量:{len(valid_descriptors)}") print(features)
方案3:使用标准聚合物连接点表示
import numpy as np from rdkit import Chem from rdkit.Chem import Descriptors from rdkit.ML.Descriptors import MoleculeDescriptors descriptors = [desc[0] for desc in Descriptors._descList] calculator = MoleculeDescriptors.MolecularDescriptorCalculator(descriptors) def computeDescriptors(mol, calculator): res = np.array(calculator.CalcDescriptors(mol)) # 填充NaN为均值 mask = np.isfinite(res) if len(res[mask]) > 0: res[~mask] = np.mean(res[mask]) return res # 将*替换为[*],符合RDKit聚合物连接点规范 processed_smiles = [s.replace('*', '[*]') for s in smiles] mol_objects = [Chem.MolFromSmiles(smile) for smile in processed_smiles] features = [computeDescriptors(x, calculator) for x in mol_objects] print(features)
内容的提问来源于stack exchange,提问作者str
相关产品推荐
相关产品推荐

