RDKit技术问询:如何将指纹转回Mol/Smiles并输出聚类结果为Smiles格式
没问题!这个需求用RDKit配合scikit-learn就能完美实现,我给你整理了一套完整的步骤和可运行代码,全程保留SMILES格式方便后续评估:
实现步骤与代码示例
1. 先安装依赖
确保你已经安装了所需的库,用pip安装即可:
pip install rdkit-pypi scikit-learn pandas numpy
2. 完整代码实现
下面的代码覆盖了从读取SMILES到输出聚类结果的全流程,每一步都有注释说明:
# 导入必要的库 from rdkit import Chem from rdkit.Chem import AllChem from rdkit import DataStructs from sklearn.cluster import AgglomerativeClustering import pandas as pd import numpy as np # ---------------------- # 第一步:读取SMILES文件 # ---------------------- # 这里分两种情况,根据你的文件格式选择: # 情况1:纯SMILES文件(每行一个SMILES,无表头) smiles_list = [] with open("input_smiles.smi", "r") as f: for line in f: smi = line.strip() if smi: # 跳过空行 smiles_list.append(smi) # 情况2:带表头的CSV文件(比如第一列是SMILES) # df = pd.read_csv("input_smiles.csv") # smiles_list = df["SMILES"].tolist() # ---------------------- # 第二步:转换为分子并生成Morgan指纹 # ---------------------- # 过滤无效SMILES,避免后续报错 valid_mols = [] valid_smiles = [] for smi in smiles_list: mol = Chem.MolFromSmiles(smi) if mol: valid_mols.append(mol) valid_smiles.append(smi) else: print(f"跳过无效SMILES: {smi}") # 生成Morgan指纹(半径2,2048位,这是常用参数,可根据需求调整) morgan_fps = [AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048) for mol in valid_mols] # 将指纹转换为numpy数组,方便聚类算法处理 fp_array = np.array([list(fp) for fp in morgan_fps]) # ---------------------- # 第三步:计算相似度并聚类 # ---------------------- # 计算Tanimoto相似度矩阵,再转换为距离矩阵(聚类算法通常用距离而非相似度) distance_matrix = [] for i in range(len(morgan_fps)): row = [] for j in range(len(morgan_fps)): tanimoto_sim = DataStructs.TanimotoSimilarity(morgan_fps[i], morgan_fps[j]) row.append(1 - tanimoto_sim) # 距离 = 1 - 相似度 distance_matrix.append(row) # 用层次聚类(适合基于预计算距离矩阵的场景) # 你可以调整n_clusters(指定聚类数)或设置distance_threshold来自动划分聚类 clusterer = AgglomerativeClustering( n_clusters=5, # 这里示例设为5类,可根据你的需求修改 affinity="precomputed", linkage="average" ) cluster_labels = clusterer.fit_predict(distance_matrix) # ---------------------- # 第四步:输出聚类结果(SMILES格式) # ---------------------- # 整理成DataFrame,方便输出和后续读取 result_df = pd.DataFrame({ "SMILES": valid_smiles, "Cluster_Label": cluster_labels }) # 推荐输出为CSV格式(保留聚类标签,后续评估更方便) result_df.to_csv("clustered_smiles.csv", index=False) # 如果需要纯SMILES+标签的文本格式(每行SMILES后跟聚类编号) with open("clustered_smiles.smi", "w") as f: for smi, label in zip(valid_smiles, cluster_labels): f.write(f"{smi} {label}\n")
3. 关键细节说明
- 无效SMILES过滤:必须过滤掉无法转换为分子的SMILES,否则会导致指纹生成失败
- 指纹参数调整:Morgan指纹的
radius和nBits可以根据分子复杂度调整,比如大分子可以用半径3,位数4096 - 聚类方法选择:这里用层次聚类是因为它支持预计算的Tanimoto距离矩阵,如果你处理超大规模数据集,可以考虑用KMeans(但需要直接用指纹数组作为输入,无需距离矩阵)
- 后续读取评估:输出的CSV可以直接用
pd.read_csv加载,纯SMILES文件可以用RDKit的Chem.SmilesMolSupplier读取,同时拆分标签
4. 优化建议(针对大数据量)
如果你的分子数量超过1万,全量计算距离矩阵会非常耗时,这时候可以:
- 用
rdkit.Chem.Similarity.NearestNeighbors找近似邻居,减少计算量 - 改用基于密度的聚类算法如DBSCAN,或者用KMeans直接处理指纹数组
内容的提问来源于stack exchange,提问作者jrgn




