[开源] 医院药品效期调拨优化系统:用生存分析+整数规划降低医院药品报废率
本项目是面向医院药剂科、财务科与院级管理者的药品效期治理工具,不依赖人工经验排期,也不做通用库存系统。它把药品批次看作有“生命曲线”的个体,用 Kaplan-Meier 生存分析建模效期衰减规律,再以整数规划(PuLP)求解跨科室调拨的全局最优解,最终交付两类可落地输出:终端彩色 CLI 报告(供值班药师快速响应),和带筛选器的交互式 HTML 报告(供药剂科主任周度复盘、财务科成本归因、院长办全院效期健康度监测)。核心模块全部由 Python 3.10+ 实现,依赖 lifelines 做生存拟合,pandas 清洗批次数据,Rich 渲染高可读终端界面,Chart.js 驱动 Web 可视化,所有分析逻辑封装为命令行入口,支持模拟数据生成、配置驱动运行、多格式结果导出。
定位与能力范围
我们不做全链路进销存,也不覆盖采购计划或供应商协同。系统边界明确锚定在「已有库存的效期风险识别与调拨干预」这一环节。当药房已完成入库、各科室已形成分散库存、但临近效期的批次尚未被主动调度时,本系统介入,不是告诉你“这批药还能放多久”,而是回答“这批药该优先发给哪个科室、调多少、不调会损失多少钱”。它服务三类典型角色:药剂科主任需要知道下周必须优先消耗的 Top 10 批次;财务科需将“濒临报废数量”“濒临报废价值”映射到月度成本报表;院长办则通过仪表盘中“紧急/预警/正常”三级分布占比,判断全院药品流转健康度是否持续劣化。系统不替代人工决策,但把原来靠 Excel 筛选+微信群协调的流程,变成可复现、可回溯、带量化依据的标准化动作。
核心功能
系统由四大引擎构成,彼此解耦、职责清晰:
模块 | 职责 | 关键技术点 | 输出形态 |
|---|---|---|---|
生存分析引擎 | 对同通用名、同规格的不同生产批次,拟合其效期生存函数,输出各批次剩余安全使用天数的置信区间 | Kaplan-Meier 非参数估计,lifelines 库实现 | 批次级优先级排序、效期分布直方图 |
调拨优化引擎 | 在满足科室最低库存约束、单次调拨量整数约束、总调拨成本最小化前提下,求解跨科室调拨方案 | PuLP 构建整数规划模型,目标函数含报废损失权重 | 调拨建议表格(源科室→目标科室→数量)、报废风险预测汇总 |
CLI 报告引擎 | 将分析结果结构化渲染为终端友好格式,用颜色区分风险等级,支持快速扫描关键数字 | Rich 库控制色彩、缩进与分隔线 | 彩色文本流,适配 Linux/macOS/Windows 终端 |
HTML 可视化引擎 | 生成离线可打开的交互式报告,内置图表联动与字段筛选器 | Chart.js 渲染动态图表,Jinja2 模板注入数据 | 单 HTML 文件,含效期分布图、科室热力图、调拨明细表 |
这四个模块共同构成一个闭环:从原始库存 JSON 数据出发,先判别哪些批次已进入“红色区域”,再计算如何用最少的调拨动作延缓报废,最后用两种形态把结论送到对应岗位手上。
使用与配置
所有操作均通过python -m src命令触发,无需安装包、不修改系统环境。你只需准备一份符合规范的库存数据(JSON 格式),或直接生成模拟数据上手验证:
python -m src generate-data --output data/inventory.json --seed 42运行分析时,可指定输入、输出路径与格式:
python -m src run-analysis --input data/inventory.json --format console python -m src run-analysis --input data/inventory.json --output output/report.html --format html若需长期使用,推荐复制配置模板并编辑config.yaml:
cp config.yaml.example config.yaml配置文件支持以下关键参数:
参数 | 说明 | 默认值 | 典型调整场景 |
|---|---|---|---|
threshold_days | 效期预警阈值(剩余天数 ≤ 此值即标为“预警”) | 30 | 财务科要求提前 45 天预警,则设为 45 |
critical_days | 效期紧急阈值(剩余天数 ≤ 此值即标为“紧急”,触发强提醒) | 7 | 临床急需药品可设为 3,延长响应窗口 |
output_format | 默认输出格式,可选 console / html | console | 日常巡检用 console,周报归档用 html |
random_seed | 控制模拟数据与部分随机过程可重现 | 42 | 调试阶段保持固定,确保结果一致 |
配置项不多,但每项都对应真实业务规则,比如critical_days不是技术参数,而是药房 SOP 中明文规定的“必须 7 天内完成处置”的硬性时限。
环境与运行
本地运行仅需 Python 3.10+,无 GPU 或特殊硬件依赖。我们坚持轻量部署原则:不强制 Docker,不依赖云服务,不设后台进程。整个流程是单次、离线、可审计的:
git clone <repository-url> cd pharmacy-expiry-allocator python -m venv venv source venv/bin/activate # Linux/macOS venv\Scripts\activate # Windows pip install -r requirements.txt依赖列表严格收敛:lifelines专注生存建模,PuLP保证整数规划求解稳定,pandas处理结构化数据,Rich和Chart.js分别负责两类终端的呈现质量。没有“全家桶”式框架,每个依赖都对应一个不可绕过的业务能力。项目自带bin/下的 shell/bat 脚本,一线药师双击即可运行,无需记忆命令。
数据与扩展
输入数据为标准 JSON,字段含义与医院 HIS 出库字段对齐,包含:药品通用名、规格、生产批号、有效期至、当前库存量、所属科室、入库日期等。示例见data/inventory_sample.json。字段设计遵循两个原则:一是兼容多数医院基础库存导出格式,二是剔除非效期相关冗余字段(如供应商、采购价),聚焦问题本质。
系统预留扩展接口:survival_engine.py支持替换为 Cox 比例风险模型(需补充协变量);optimizer.py的目标函数可加入运输成本、科室调剂频次惩罚项;visualizer.py接收任意新增图表类型。所有扩展均不破坏原有 CLI/HTML 双通道输出能力。我们不预设“未来要加 AI 预测”,但确保当你真有新模型要集成时,只需改一个模块,其余部分照常工作。
限制与说明
本系统有明确的能力边界,说明文档中已如实标注:
- 不处理效期造假、标签脱落等物理异常,仅基于录入的有效期至字段运算;
- 不对接实时库存接口,数据需定期手动导入(建议每日/每周导出一次);
- 整数规划求解在超大规模科室(>100)+超多批次(>10,000)时可能耗时增加,此时建议按药品大类分批运行;
- 生存分析依赖历史报废数据校准,首次使用建议用模拟数据跑通流程,再逐步接入真实数据。
这些不是缺陷,而是设计选择,我们优先保障中小规模医院药房在普通笔记本上 5 秒内获得可靠结论,而非追求理论上的全场景覆盖。真正的效期治理,从来不是比谁的模型更复杂,而是比谁的结论更及时、更可执行、更经得起翻查。
项目地址:
https://github.com/nexorin9/pharmacy-expiry-allocator
