Python实现Excel药物不良反应分类宏失败求助
解决Excel药物不良反应分组及格式设置问题(基于Pandas+Openpyxl)
以下是完整可运行的代码,附带关键逻辑说明和常见错误排查:
import pandas as pd from openpyxl import load_workbook from openpyxl.styles import PatternFill from openpyxl.utils.dataframe import dataframe_to_rows import os # 定义文件路径(兼容多系统) desktop_path = os.path.expanduser("~/Desktop/Pharm Exam III Drugscopy.xlsx") # 指定要处理的工作表 target_sheets = ["Antidepressants and Mood", "Immunomodulators", "Drugs of Abuse"] # 存储不良反应与对应药物的映射 adverse_drug_dict = {} # 1. 遍历工作表提取并清洗数据 for sheet_name in target_sheets: # 仅读取B、D列,提升效率 df = pd.read_excel(desktop_path, sheet_name=sheet_name, usecols=["B", "D"]) df.columns = ["Drug_Name", "Adverse_Effects"] # 提取"-"后内容(兼容"- "格式,仅分割第一个"-") df["Cleaned_Adverse"] = df["Adverse_Effects"].apply( lambda x: x.split("-", 1)[1].strip() if isinstance(x, str) and "-" in x else "" ) # 过滤无效条目 df = df[df["Cleaned_Adverse"] != ""] # 填充映射字典,保证药物唯一 for _, row in df.iterrows(): adverse = row["Cleaned_Adverse"] drug = row["Drug_Name"] if adverse not in adverse_drug_dict: adverse_drug_dict[adverse] = [] if drug not in adverse_drug_dict[adverse]: adverse_drug_dict[adverse].append(drug) # 2. 构建输出DataFrame,对齐所有列行数 max_row_count = max(len(drugs) for drugs in adverse_drug_dict.values()) output_data = {} for adverse, drugs in adverse_drug_dict.items(): # 用空值填充短列表,避免写入Excel时错位 output_data[adverse] = drugs + [""] * (max_row_count - len(drugs)) output_df = pd.DataFrame(output_data) # 3. 写入Excel并设置列颜色 # 加载原工作簿,避免覆盖原始数据 wb = load_workbook(desktop_path) # 新建汇总表(若已存在则删除) if "Adverse_Summary" in wb.sheetnames: del wb["Adverse_Summary"] ws = wb.create_sheet("Adverse_Summary") # 将DataFrame写入工作表 for row_idx, row in enumerate(dataframe_to_rows(output_df, index=False, header=True), 1): for col_idx, value in enumerate(row, 1): ws.cell(row=row_idx, column=col_idx, value=value) # 4. 为各列设置不同背景色 # 预设一组填充色(可按需扩展) fill_colors = [ "FFE5E5", "E5F2FF", "E5FFE5", "FFF5E5", "F5E5FF", "E5FFFF", "FFF0E5", "E5F5FF", "F5FFE5", "FFE5F5" ] # 遍历列设置颜色(循环使用预设色) for col_idx, _ in enumerate(output_df.columns, 1): fill = PatternFill( start_color=fill_colors[(col_idx-1) % len(fill_colors)], end_color=fill_colors[(col_idx-1) % len(fill_colors)], fill_type="solid" ) # 为表头和所有数据行设置颜色 for row_idx in range(1, max_row_count + 2): ws.cell(row=row_idx, column=col_idx).fill = fill # 保存为新文件,不覆盖原数据 wb.save(desktop_path.replace(".xlsx", "_processed.xlsx")) print("处理完成,结果已保存至桌面的_processed.xlsx文件")
关键逻辑说明
数据清洗:
- 用
split("-",1)仅分割第一个“-”,避免多“-”场景下的错误提取 - 用
strip()去除“- ”后的空格,保证不良反应名称统一 - 过滤空条目,避免无效数据干扰
- 用
唯一值处理:
- 通过字典存储映射,写入前判断药物是否已存在,确保每个不良反应下的药物唯一
Excel写入对齐:
- 找出最长药物列表长度,用空值填充短列表,解决不同列行数不一致导致的错位问题
样式设置:
- 循环使用预设颜色,确保列颜色不重复
- 同时设置表头和数据行的背景色,保证格式统一
常见错误排查
- 路径错误:直接使用
/Desktop/未兼容多系统,代码中用os.path.expanduser解决 - 字符串处理错误:未处理
"- "格式或分割所有“-”,导致不良反应提取错误 - 重复数据:未判断药物是否已在列表中,导致同一药物重复出现
- 写入错位:未对齐列行数,导致Excel中数据错位
- 样式失效:未正确遍历行/列,导致颜色设置未生效
内容的提问来源于stack exchange,提问作者pythonpaul007
相关产品推荐
相关产品推荐

