RDKit计算Morgan分子指纹Dice相似度时出现参数类型报错
Morgan指纹计算Dice相似度参数不匹配问题解决
问题现象
基于BindingDB数据库的MorganFingerprints计算DiceSimilarity时,代码运行至数据库遍历进度约40%时持续抛出参数错误,原代码如下:
tqdm._instances.clear() df_matrix = pd.DataFrame() df_matrix['BindingDB Reactant_set_id'] = df_database['BindingDB Reactant_set_id'] df_matrix.index = list(df_database['BindingDB Reactant_set_id']) cols = list(df_metabolites['Molecule']) for i in tqdm(range(len(mol_list2)),desc = 'Calculating Dice Similarity'): col = cols[I] df_matrix[col] = [DataStructs.DiceSimilarity(mfp2[i],mfp1[j]) for j in range(len(mfp1))] df_matrix = df_matrix.drop(columns = ['BindingDB Reactant_set_id'])
报错核心信息:
ArgumentError: Python argument types in rdkit.DataStructs.cDataStructs.DiceSimilarity(UIntSparseIntVect, int) did not match C++ signature
根因分析
- 核心错误:传入
DiceSimilarity的第二个参数为整数int类型,不符合函数要求的入参规则——该函数要求传入两个同类型的RDKit指纹对象(支持SparseIntVect、ExplicitBitVect、SparseBitVect类型)。代码运行到40%才触发报错,是因为mfp1列表前40%的元素是正常生成的Morgan指纹,后续位置存在无效整数值:通常是对应分子的SMILES解析失败、指纹生成流程出错时,没有做异常捕获,将错误码、索引值这类整数存入了指纹列表,遍历到该位置时触发类型错误。 - 代码笔误:循环内
col = cols[I]使用了大写I,和循环变量小写i不一致,运行到该行会触发变量未定义的NameError。 - 潜在风险:若
mfp1和mfp2生成时用了不同的指纹生成方法(比如一个返回计数型稀疏向量、一个返回比特型向量),也会触发类型不匹配错误。
修复步骤
- 第一步:修正代码笔误,将
col = cols[I]的大写I改为小写i。 - 第二步:在指纹生成环节增加有效性校验,过滤解析失败的无效分子,禁止非指纹类型的值存入
mfp1、mfp2列表,参考实现:
from rdkit import Chem from rdkit.Chem import AllChem # 定义带校验的Morgan指纹生成函数,分子解析/指纹生成失败直接返回None def gen_morgan_fp(smiles, radius=2, use_count=False, nBits=2048): mol = Chem.MolFromSmiles(smiles) if mol is None: return None if use_count: # 返回计数型稀疏指纹(SparseIntVect) return AllChem.GetMorganFingerprint(mol, radius) else: # 返回比特型指纹(ExplicitBitVect) return AllChem.GetMorganFingerprintAsBitVect(mol, radius, nBits=nBits) # 生成数据库分子指纹列表,同时记录有效分子索引,避免结果错位 mfp1 = [] valid_db_idx = [] for idx, smi in enumerate(df_database['SMILES']): # 替换为你存储SMILES的实际列名 fp = gen_morgan_fp(smi) if fp is not None: mfp1.append(fp) valid_db_idx.append(idx) # 生成代谢物分子指纹列表,保证和数据库侧指纹类型一致 mfp2 = [] valid_met_idx = [] for idx, smi in enumerate(df_metabolites['SMILES']): # 替换为你存储代谢物SMILES的实际列名 fp = gen_morgan_fp(smi) if fp is not None: mfp2.append(fp) valid_met_idx.append(idx)
- 第三步:调整相似度计算逻辑,匹配过滤后的有效数据集,增加类型兜底校验,修正后代码如下:
import pandas as pd from tqdm import tqdm from rdkit import DataStructs tqdm._instances.clear() # 仅保留有效分子的ID作为结果矩阵索引 valid_db_ids = df_database.iloc[valid_db_idx]['BindingDB Reactant_set_id'].tolist() df_matrix = pd.DataFrame(index=valid_db_ids) cols = [df_metabolites.iloc[i]['Molecule'] for i in valid_met_idx] for i in tqdm(range(len(mfp2)), desc='Calculating Dice Similarity'): current_col = cols[i] sim_values = [] fp2 = mfp2[i] for j in range(len(mfp1)): fp1 = mfp1[j] # 类型兜底校验,避免异常值中断运行 if type(fp1) != type(fp2): sim_values.append(None) continue sim_values.append(DataStructs.DiceSimilarity(fp2, fp1)) df_matrix[current_col] = sim_values
内容的提问来源于stack exchange,提问作者dandan
相关产品推荐
相关产品推荐

