
本文介绍如何正确读取zinc数据库导出的smi文件(空格或制表符分隔的文本格式),并将其结构化为带smiles和化合物id两列的pandas dataframe,避免手动逐行读取导致换行符残留、列错位等问题。
本文介绍如何正确读取zinc数据库导出的smi文件(空格或制表符分隔的文本格式),并将其结构化为带smiles和化合物id两列的pandas dataframe,避免手动逐行读取导致换行符残留、列错位等问题。
ZINC数据库导出的 .smi 文件并非纯单列SMILES文本,而是一种轻量级制表格式:首列为SMILES字符串,第二列为ZINC ID(如 ZINC000016090786),两列之间以一个或多个空白字符(空格或制表符)分隔。若直接使用 f.readlines() 读取,不仅会保留每行末尾的 \n 换行符,还会丢失列结构信息,导致DataFrame中所有数据挤在单列、ID与SMILES混杂,无法用于后续化学信息学分析(如RDKit分子解析、QSAR建模等)。
推荐使用 pandas.read_csv() 直接解析,关键在于指定正确的分隔符:
import pandas as pd
# 正确方式:用正则 \s+ 匹配任意空白分隔(兼容空格、制表符、多空格)
df = pd.read_csv('substances.smi', sep=r'\s+', header=None, engine='python')
# 显式命名列(ZINC标准格式:SMILES + ID)
df.columns = ['SMILES', 'ID']
# 可选:去除SMILES两端空白及换行影响(read_csv已自动处理,但可双重保险)
df['SMILES'] = df['SMILES'].str.strip()
df['ID'] = df['ID'].str.strip()
print(df.head())输出示例:
SMILES ID 0 N[C@H](CCc1ccc(N(CCCl)CCCl)cc1)C(=O)O ZINC000016090786 1 N[C@@H](CCCc1ccc(N(CCCl)CCCl)cc1)C(=O)O ZINC000002033385 2 N[C@H](CCCc1ccc(N(CCCl)CCCl)cc1)C(=O)O ZINC000001763088
⚠️ 注意事项:
- 不要使用 sep=' '(单空格):ZINC文件常含不等宽空格或混合制表符,会导致列解析错位;sep='\s+' 是鲁棒性最佳实践。
- 避免省略 header=None:SMI文件无标题行,否则首行会被误判为列名。
- 若遇到编码错误(如 UnicodeDecodeError),添加 encoding='utf-8' 或 encoding='latin-1' 参数。
- 后续如需用RDKit处理,可快速生成分子对象列:
from rdkit import Chem df['Mol'] = df['SMILES'].apply(lambda x: Chem.MolFromSmiles(x)) df = df.dropna(subset=['Mol']) # 过滤无效SMILES
此方法简洁、高效、可复现,是连接ZINC化学数据与Python数据分析生态的标准起点。

















