You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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指纹的radiusnBits可以根据分子复杂度调整,比如大分子可以用半径3,位数4096
  • 聚类方法选择:这里用层次聚类是因为它支持预计算的Tanimoto距离矩阵,如果你处理超大规模数据集,可以考虑用KMeans(但需要直接用指纹数组作为输入,无需距离矩阵)
  • 后续读取评估:输出的CSV可以直接用pd.read_csv加载,纯SMILES文件可以用RDKit的Chem.SmilesMolSupplier读取,同时拆分标签

4. 优化建议(针对大数据量)

如果你的分子数量超过1万,全量计算距离矩阵会非常耗时,这时候可以:

  • rdkit.Chem.Similarity.NearestNeighbors找近似邻居,减少计算量
  • 改用基于密度的聚类算法如DBSCAN,或者用KMeans直接处理指纹数组

内容的提问来源于stack exchange,提问作者jrgn

火山引擎 最新活动