Python迭代逻辑异常:Kinase数据遍历输出结果过少问题排查
问题
我编写的Python代码意图如下:遍历Kinase Data工作表(共12000行),提取pdb ID、kinase group、kinase family、kinase name等信息,再遍历Drug Data工作表,匹配相同pdb ID对应的drug name,最终将匹配结果写入Python Source Doc.xlsx工作表。但实际运行后仅得到200行输出,远低于预期。
以下是我的代码:
import openpyxl from openpyxl.utils.dataframe import dataframe_to_rows from openpyxl import Workbook import pandas as pd # Open Excel Workbook that contains all the requested kinases and ligands wrkbk = openpyxl.load_workbook("Python Source Doc.xlsx") sh = wrkbk.active wrkbk2 = openpyxl.load_workbook('Kinase Data.xlsx') sh2 = wrkbk2.active wrkbk3 = openpyxl.load_workbook('Drug Data.xlsx') sh3 = wrkbk3.active #while True: for i in range(2, sh2.max_row+1): pdb = sh2.cell(row=i, column=9).value kinase_group = sh2.cell(row=i, column=3).value kinase_family = sh2.cell(row=i, column=2).value kinase_name = sh2.cell(row=i, column=1).value for i in range(2, sh3.max_row+1): if pdb == sh3.cell(row=i, column=3).value: drug_name = sh3.cell(row=i, column=1).value cell = sh.cell(row=i, column=1) cell.value = kinase_group cell = sh.cell(row=i, column=2) cell.value = kinase_family cell = sh.cell(row=i, column=3) cell.value = kinase_name cell = sh.cell(row=i, column=4) cell.value = drug_name cell = sh.cell(row=i, column=5) cell.value = pdb wrkbk.save('Python Source Doc.xlsx')
问题分析
代码存在三个核心问题,导致输出结果远低于预期:
- 循环变量冲突:外层遍历Kinase Data的循环和内层遍历Drug Data的循环都用了
i作为变量,内层循环会直接覆盖外层i的值。比如Drug Data共200行,内层循环跑完后i会变成200,外层循环直接终止,无法遍历完12000行Kinase Data。 - 写入行号错误:写入结果时使用的是内层循环的
i,这会导致所有匹配结果都覆盖到Drug Data对应的行范围内,大量数据被重复覆盖,最终只保留最后一批写入的内容。 - 效率与匹配逻辑缺陷:双重嵌套循环遍历大表效率极低,且未处理一个pdb对应多个drug的情况,只会保留最后一个匹配的drug,还会重复写入同一行。
修复方案
方案一:用Pandas实现(推荐,高效且简洁)
Pandas的merge功能可以直接按pdb ID关联两个表,自动处理多匹配情况,代码更简洁高效:
import pandas as pd # 读取Kinase Data,提取需要的列(原列1、2、3、9对应索引0、1、2、8) kinase_df = pd.read_excel('Kinase Data.xlsx', usecols=[0, 1, 2, 8]) kinase_df.columns = ['kinase_name', 'kinase_family', 'kinase_group', 'pdb_id'] # 读取Drug Data,提取需要的列(原列1、3对应索引0、2) drug_df = pd.read_excel('Drug Data.xlsx', usecols=[0, 2]) drug_df.columns = ['drug_name', 'pdb_id'] # 按pdb_id匹配两个表,仅保留双方都存在的匹配项(如需保留所有Kinase数据可改how='left') merged_df = pd.merge(kinase_df, drug_df, on='pdb_id', how='inner') # 将结果写入目标文件,覆盖原有内容 with pd.ExcelWriter('Python Source Doc.xlsx') as writer: merged_df.to_excel(writer, index=False)
方案二:修复openpyxl版本(适合坚持用openpyxl的场景)
解决变量冲突问题,同时用字典预存Drug Data的匹配关系提升效率:
import openpyxl # 打开各工作簿 wrkbk = openpyxl.load_workbook("Python Source Doc.xlsx") sh = wrkbk.active wrkbk2 = openpyxl.load_workbook('Kinase Data.xlsx') sh2 = wrkbk2.active wrkbk3 = openpyxl.load_workbook('Drug Data.xlsx') sh3 = wrkbk3.active # 预存Drug Data的pdb与drug映射:一个pdb可能对应多个drug,用列表存储 pdb_drug_map = {} for j in range(2, sh3.max_row + 1): pdb = sh3.cell(row=j, column=3).value drug_name = sh3.cell(row=j, column=1).value if pdb not in pdb_drug_map: pdb_drug_map[pdb] = [] pdb_drug_map[pdb].append(drug_name) # 遍历Kinase Data,逐行写入匹配结果 output_row = 2 # 从第2行开始写入结果 for i in range(2, sh2.max_row + 1): pdb = sh2.cell(row=i, column=9).value kinase_group = sh2.cell(row=i, column=3).value kinase_family = sh2.cell(row=i, column=2).value kinase_name = sh2.cell(row=i, column=1).value # 如果当前pdb有匹配的drug,逐个写入 if pdb in pdb_drug_map: for drug_name in pdb_drug_map[pdb]: sh.cell(row=output_row, column=1).value = kinase_group sh.cell(row=output_row, column=2).value = kinase_family sh.cell(row=output_row, column=3).value = kinase_name sh.cell(row=output_row, column=4).value = drug_name sh.cell(row=output_row, column=5).value = pdb output_row += 1 # 写完一行后切换到下一行 wrkbk.save('Python Source Doc.xlsx')
内容的提问来源于stack exchange,提问作者DJ_Fox
相关产品推荐
相关产品推荐

