如何用RDKit将大型SDF文件转为DataFrame且降低内存占用?
处理大型SDF文件转DataFrame的内存优化方案
1. 分块读取SDF文件
PandasTools.LoadSDF默认一次性加载全量数据,可通过RDKit的SDMolSupplier配合分块逻辑逐批处理,避免内存瞬间占满:
from rdkit import Chem import pandas as pd def sdf_to_df_chunked(sdf_path, chunk_size=10000): supplier = Chem.SDMolSupplier(sdf_path) chunks = [] chunk = [] for idx, mol in enumerate(supplier): if mol is None: continue # 跳过无法解析的无效分子 # 仅提取分析所需的字段,不要加载SDF中全部属性 data = { 'SMILES': Chem.MolToSmiles(mol), 'ID': mol.GetProp('_Name'), # 按需添加其他需要的属性,比如:'MolecularWeight': mol.GetProp('MW') } chunk.append(data) if (idx + 1) % chunk_size == 0: chunks.append(pd.DataFrame(chunk)) chunk = [] # 处理剩余未达分块大小的数据 if chunk: chunks.append(pd.DataFrame(chunk)) return pd.concat(chunks, ignore_index=True) df = sdf_to_df_chunked('Datatest/0 chemdiv_PPI.sdf', chunk_size=10000)
2. 压缩DataFrame数据类型
合并分块后,针对性调整数据类型,进一步降低内存占用:
# 重复值较多的字符串列转category类型 df['ID'] = df['ID'].astype('category') # 数值列根据取值范围向下转换类型(如有数值属性时使用) # df['MolecularWeight'] = pd.to_numeric(df['MolecularWeight'], downcast='float')
3. 用Dask并行处理超大规模数据
如果分子数量远超单进程处理能力,可使用Dask实现分块并行计算,它的API与Pandas高度兼容:
from dask.dataframe import from_pandas from rdkit import Chem import pandas as pd supplier = Chem.SDMolSupplier('Datatest/0 chemdiv_PPI.sdf') df_list = [] for mol in supplier: if mol: df_list.append(pd.DataFrame({ 'SMILES': [Chem.MolToSmiles(mol)], 'ID': [mol.GetProp('_Name')] })) # 转为Dask DataFrame,指定分区数(建议与CPU核心数匹配) dask_df = from_pandas(pd.concat(df_list, ignore_index=True), npartitions=8) # 后续分析直接用Dask API,需最终结果时再转Pandas # final_df = dask_df.compute()
4. 提前过滤无效数据
始终保留跳过无效分子的逻辑,避免无效数据占用内存,以上代码中已包含if mol is None: continue的判断。
内容的提问来源于stack exchange,提问作者jacobdavis
相关产品推荐
相关产品推荐

