英格兰每家诊所的处方账本 — OpenPrescribing

GP 诊所逐月处方 / BNF 五级编码 / OGL 开放下载

来源 https://openprescribing.net/发布时间: 2026-10-26最后更新: 2026-10-26 阅读 6
英格兰每家诊所的处方账本 — OpenPrescribing

信息速览

数据集名称英格兰每家诊所的处方账本 — OpenPrescribing
数据类型元数据,原始数据链接,文献引用,本体映射
规模不适用(聚合数据,覆盖英格兰六千余家 GP 诊所的全部门诊处方)
接入方式https://openprescribing.net/
AI 就绪度

OpenPrescribing 不是一个「药品库」,而是一台观测英格兰初级保健处方行为的仪器。它把 NHS Business Services Authority(下文简称 NHSBSA)每月结算出来的逐条处方,压缩成「诊所 × 药品 × 月份」的三维账本,让任何一个会用浏览器的人都能查到自己家附近那家全科诊所过去十年开了多少他汀、多少抗生素、多少降糖药。上游的 English Prescribing Dataset(EPD)每月新增约一千七百万行,平台让这堆数变成了能排序、能绘图、能导出的一组答案。

它真正难以替代的地方,是覆盖深度和对比能力同时成立:英格兰六千多家 GP 诊所、十余年、逐月、按 BNF 药品编码的完整处方记录,可以按任意组合实时横向排位。这件事在全世界范围内几乎没有第二个同等体量的公开版本。美国的 Medicare Part D 有类似的处方明细,但按年度、按药品,没有诊所这一层;北欧的登记库有患者级链接,却要申请、要付费、也未必逐月公开。把「哪家诊所、哪个月、用什么药、花了多少钱」同时公开到这一粒度,是英格兰这套结算制度独有的副产物。

正因为它是处方行为的观测台而不是临床数据库,它的能力边界必须一开始就说清楚:没有患者、没有诊断、没有结局。凡是想从它里面读出发病率、依从性、疗效的尝试,都会在第一步就错。本文按「平台与数据集的关系、编码体系、取数路径、质量与治理」四层展开,所有硬数字都可回到附录 A 复算。一屏速览见下表。

维度 内容
中文名 OpenPrescribing(英格兰初级保健开放处方查询平台)
建设方 牛津大学 EBM DataLab(纳菲尔德初级保健健康科学系)
上游数据方 NHS Business Services Authority(NHSBSA)
数据集正式名 English Prescribing Dataset(EPD),2021 年 2 月起另有 EPD with SNOMED Code
记录粒度 处方者机构 × BNF 呈报形式 × 月份
单月规模 官方描述约 1,700 万行/月
单月文件体积 2026 年 8 月文件 7.4 GB(CSV 未压缩计)
时间跨度 EPD 原始文件 2014-01 至 2026-08;分析用长期序列可回溯至 1998
空间范围 英格兰开具,英格兰与威尔士、苏格兰、三属岛及马恩岛调配
编码体系 BNF 五级 + 可选产品/呈报形式扩展;2021 年起加 SNOMED CT 与 dm+d
核心度量 项目数(ITEMS)、数量(QUANTITY)、净原料成本(NIC)、实际成本(ACTUAL_COST)
取数方式 平台 REST API(部分端点免密钥)/ 月度全量 CSV / 平台图表页
许可 Open Government Licence v3.0(OGL-UK-3.0)
患者级信息 无
是否可商用 可以,但须标注「NHSBSA Copyright」并遵守 OGL 条款
最典型的误用 把项目数当患者数,除以人口算患病率

§1 它要解决的具体麻烦

1.1 数据早就公开了,麻烦在于公开得没法用

英格兰的初级保健处方数据自 2011 年起就按月公开,这件事在卫生数据圈里被反复引用。可「公开」与「可用」之间隔着一整套工程。每个月落地的是一份七百多万行的 CSV,每行一个诊所一种药一个月的汇总;列名是全大写英文缩写,药品名是 BNF 的短写,机构代码每隔几年换一轮,编码体系本身也在改版。想回答一个再朴素不过的问题——「我们这一片的诊所,抗生素用得比别处多吗」——需要先下载十几份文件、处理编码变更、把机构对到人口、再写一段归一化代码。绝大多数想提问的人,没有这三天的工夫。

OpenPrescribing 解决的正是这一段落差。它不做新的统计,也不重新定义指标,只做三件事:把数据装进数据库、把常用查询做成固定网址、把横向排位算好并公开方法。平台的方法学论文(Curtis 与 Goldacre,BMJ Open,2018)把这个定位说得很直白:数据早已公开,但静态报告无法让人就自己关心的话题逐层下钻,因此需要一个可以自由交互的入口。

这一段的收益是复利式的。一次工程投入,之后每一个提问的人都省掉了那三天。这也是它被称为「基础设施」而不是「数据集」的理由——它本身不产出新知识,但它把产出新知识的边际成本压到了接近零。

1.2 三条常见的错误期待

第一条期待是把它当成「英格兰的处方药数据库」。药品说明书、适应症、禁忌、相互作用,这些它一样都不提供。它记录的是「谁开了、开了多少、花了多少」,不是「为什么开、开了给谁、开了有没有效」。把它当药理信息源用,第一步就会扑空。

第二条期待是把它当成「患病人群的抽样」。每一行背后可能是一个人,也可能是一千个人;项目数计量的是处方次数,不是人头。用项目数去除以登记人口再乘一千,得到的数字看起来像患病率,实际上叫处方强度,两者的关系取决于处方时长、续方规则和病人是否同时在别处就诊。

第三条期待是把它当成「实时」。数据有固定的滞后:官方说明按月更新,通常在每月二十日前后,且滞后两个月——一月份的数据在三月份发布。想用它做当月的药事监控,时间上就对不上;它能做的是趋势和回顾,不是当日预警。

1.3 它能给到的与给不到的

把需求摊开来对照,比一句话概括更有用。下表左列写的是问题,不是功能。

你的需求 它给的 够不够
某药在某地的用量是否异常 化学物质层级的每千患者项目数,可按诊所、PCN、ICB 排名 够,但需自行核对名单人口口径
某诊所的抗生素使用是否超标 第五章抗感染药的整体与分药排名,附全国与同侪中位数 够用于初筛,定性仍需临床复核
某药品的处方成本变化 月度 NIC 与实际成本序列,可按机构拆分 够,注意 2024 年 4 月起成本算法变更
一个新药在多快铺开 上市后逐月的处方项目数曲线,可按地区拆分 够,能看到采纳速度差异
某疾病在人群中的患病率 无诊断字段,无患者标识 不够,换别的数据源
患者是否按医嘱服药 无处方兑现、无服药记录 不够,属依从性研究范畴
某位医生的处方偏好 最低到机构,不到个人 不够,且不应从聚合数据反推
某个患者的用药史 完全没有 不够,属患者级数据
药物不良事件发生率 无结局字段 不够,需 Yellow Card 等体系
处方是否合理(指南一致性) 处方量与指南推荐量可对照 部分够,合理性的临床判断仍要人做
某药在私立机构的处方 仅「私方」标记下的有限部分 大多不够,覆盖不完整
药房直接供应(PGD)的药 明确排除在 EPD 之外 不够,需另找 Pharmacy First 等数据

1.4 你的处境与它能帮到的事

同样一份数据,不同处境的人该拿它做什么完全不同。下表左列是处境,右列是下一步动作,中间才是数据能提供的部分。

你的处境 它能帮你什么 下一步该做什么
你在做卫生服务研究,想找「处方行为变异」的选题 提供全量、免申请、可复算的暴露变量 先用平台排名找出候选化学物质,再用全量 CSV 复算
你在 ICB 做药事管理,季度要交用药合理性报告 给出本机构在同类机构中的分位 取本机构与同侪的月度序列,做差分对比
你在做卫生经济学评估,需要一个成本基线 提供 NIC 与实际成本两套口径 确认用哪一套,注明 2024 年 4 月的算法断点
你是临床药师,想推动一次处方精简 找出本地异常高、全国普遍低的化学物质 用异常值清单约谈,而非用排名定罪
你在训练一个处方预测模型 提供机构×药品×月份的长面板 先解决机构代码变更与 BNF 编码漂移
你在写科普或调查报道 提供可核对的公开数字与固定网址 每个数字都贴上游链接,注明月份与口径
你只想查自家诊所开了多少药 一个网址、一个搜索框 直接查,不必下载任何文件
你需要患者级数据做临床研究 帮不上 走 CPRD、OpenSAFELY 等受控通道

1.5 一句话判断

它是处方行为的观测台,不是药品说明书库,更不是临床结局库;把这句定位记住,九成的误用都能提前避开。

1.6 不适合谁:四条边界

第一条边界:需要患者级信息的研究。要做个体化的用药轨迹、合并用药模式、依从性与结局的关联,这个数据源在第一列就交白卷。它的每一行都是聚合值,连「同一个患者开了两次」这件事都看不到。

第二条边界:需要诊断信息的研究。没有 ICD 编码,没有 Read 码,没有 SNOMED 诊断。药品与适应症之间是多对多关系——同一个他汀既用于二级预防也用于家族性高胆固醇,同一个抗抑郁药既治抑郁也治神经痛。用药品反推疾病,误差不可控。

第三条边界:需要实时监控的场景。两个月滞后加上月度聚合,让它天然做不了「本周哪个诊所开错了药」这类即时拦截。它适合的是回顾性审计、趋势监测、干预前后的对比。

第四条边界:需要评价个人的场景。公布层级止于机构。即便技术上可以把机构异常与某位医生的执业习惯对上号,那也只是推断,不是证据,而且在治理上越界。

§2 数据构成与规格

2.1 平台与数据集:两层结构,不要混为一谈

先把关系理顺,后面的所有数字才有归属。NHSBSA 是数据的产房:英格兰的处方经药房调配后,向 NHSBSA 的处方服务机构申报结算,结算系统按月导出一份逐条明细,这就是 EPD。EPD 以 CSV 形式放在 NHSBSA 的开放数据平台上,一个月份一个文件,按 OGL-UK-3.0 开放。

OpenPrescribing 是数据的加工车间与展厅:它把 EPD 装进自己的数据库,按 BNF 层级重建索引,算出每千患者的标准化指标,做成固定网址的图表,并对外开放一个 REST API。它也提供全量的月度下载,形态是「每个月一个文件」。

层 角色 产物 谁维护 更新节奏 许可
上游结算 处方申报与结算 结算台账(内部) NHSBSA 处方服务机构 每月滚动 不适用
上游发布 开放数据发布 EPD 月度 CSV NHSBSA 开放数据平台 每月,滞后约两月 OGL-UK-3.0
平台承接 清洗、索引、指标 数据库与图表 牛津 EBM DataLab 每月跟随 同 OGL
平台出口 查询与下载 REST API、CSV、图表页 牛津 EBM DataLab 实时查询 同 OGL
咨询出口 定制分析 报告与仪表板 同一团队(服务化) 按项目 另行约定

这个两层结构带来一个实用推论:平台的图表页给的是「已经算好的答案」,上游 CSV 给的是「可以自己算的原料」。两者的数字应当一致,但一致性需要自己核。核的办法是挑一个月、挑一个化学物质,用 CSV 加总后去对平台页面上的数字,差额应当在舍入范围内。

2.2 字段的完整字典

EPD with SNOMED Code 的现行文件有 27 列。下表按「机构、药品、度量、标识」四组归类,逐列写清含义与坑点。字段名以 2026 年 8 月文件的实际表头为准。

列名 中文 类型 取值示例 用法与坑点
YEAR_MONTH 年月 文本 2026-08 注意:新版为「年-月」,旧版 EPD 为 202401 六位数字
REGIONAL_OFFICE_NAME 英格兰区域名 文本 MIDLANDS 七区域制,2022 年之后稳定
REGIONAL_OFFICE_CODE 区域代码 文本 Y60 与名称一一对应
ICB_NAME 整合照护委员会名 文本 NHS WEST YORKSHIRE ICB 2022 年 7 月起取代 CCG
ICB_CODE 整合照护委员会代码 文本 QWO 与 PCO_CODE 不完全同源
PCO_NAME 初级保健组织名 文本 NHS WEST YORKSHIRE ICB - 36J 带后缀编号,做地名匹配时要先剥离
PCO_CODE 初级保健组织代码 文本 36J00 历史含 CCG,2022 年后为 ICB
PRACTICE_NAME 处方者机构名 文本 THORNELOE LODGE SURGERY 含 GP、门诊、监狱医疗等非 GP 机构
PRACTICE_CODE 处方者机构代码 文本 M81037 主键之一;机构合并会沿用旧码
ADDRESS_1 地址一 文本 29 BARBOURNE ROAD 可空
ADDRESS_2 地址二 文本 WORCESTER 可空
ADDRESS_3 地址三 文本 空 大量为空
ADDRESS_4 地址四 文本 空 约四分之一行为空
POSTCODE 邮编 文本 WR1 1RU 少数为空,不可作为主键
BNF_CHEMICAL_SUBSTANCE_CODE 化学物质码 文本 0103050L0 九位药码或四位器具码,层级见 2.3
BNF_CHEMICAL_SUBSTANCE 化学物质名 文本 Lansoprazole 器具类会是「Eye Products」这类类目名
BNF_PRESENTATION_CODE 呈报形式码 文本 0103050L0AAABAB 药类十五位,器具类十一位
BNF_PRESENTATION_NAME 呈报形式名 文本 Lansoprazole 30mg gastro-resistant capsules 含剂型与规格,是「哪一档剂量」的证据
BNF_CHAPTER_PLUS_CODE 章节 文本 01: Gastro-Intestinal System 「两位数字 + 冒号 + 空格 + 名」,截取前两位即可
QUANTITY 单张处方量 数值 28. 末尾带点,需转浮点
ITEMS 项目数 数值 7 该呈报形式在本月的处方条数
TOTAL_QUANTITY 总数量 数值 196. 等于 QUANTITY × ITEMS,已算好
ADQ_USAGE 日均用量 数值 0. 多数行为 0,不可依赖
NIC 净原料成本 数值 174.3 按基本药价计的金额,英镑
ACTUAL_COST 实际成本 数值 165.2 扣减折扣与加成后的金额,英镑
UNIDENTIFIED 未识别标记 文本 N 极少数为 Y,表示无法归到诊所
SNOMED_CODE SNOMED CT 码 文本 3305911000001106 2021-02 起有值,可与 dm+d 对齐

字段表里最容易出错的三处:YEAR_MONTH 的格式在 2021 年前后变过;PCO_CODE 在 2022 年 7 月从 CCG 切到 ICB,跨年拼接会断;QUANTITY 的计量单位随药品变化,片、毫升、克、支混在一起,不能跨药加总。

2.3 一条记录的完整解剖

拿 2026 年 8 月真实文件里的第一段结构做样本,它的原始形态如下(保留原始引号与小数尾点,便于核对解析器是否写对)。

"YEAR_MONTH","REGIONAL_OFFICE_NAME","ICB_NAME","PCO_NAME","PCO_CODE","PRACTICE_NAME","PRACTICE_CODE","POSTCODE","BNF_CHEMICAL_SUBSTANCE_CODE","BNF_CHEMICAL_SUBSTANCE","BNF_PRESENTATION_CODE","BNF_PRESENTATION_NAME","BNF_CHAPTER_PLUS_CODE","QUANTITY","ITEMS","TOTAL_QUANTITY","ADQ_USAGE","NIC","ACTUAL_COST","UNIDENTIFIED","SNOMED_CODE"
"2026-08","MIDLANDS","NHS HEREFORDSHIRE AND WORCESTERSHIRE INTEGRATED CARE BOARD","NHS HEREFORDSHIRE AND WORCESTERSHIRE ICB - 18C","18C00","THORNELOE LODGE SURGERY","M81037","WR1 1RU","2002","Arm Sling/Bandages","20020200822","K-Lite bandage 10cm x 4.5m","20: Dressings","10.",1,"10.","0.","11.","9.92671","N","9598311000001106"
"2026-08","MIDLANDS","NHS HEREFORDSHIRE AND WORCESTERSHIRE INTEGRATED CARE BOARD","NHS HEREFORDSHIRE AND WORCESTERSHIRE ICB - 18C","18C00","THORNELOE LODGE SURGERY","M81037","WR1 1RU","2003","Wound Management & Other Dressings","20030100074","Mepore dressing 7cm x 8cm","20: Dressings","12.",3,"36.","0.","4.32","3.93082","N","18411000001108"
#-- 其余列在真实文件中为 ADDRESS_1 至 ADDRESS_4,本样本为节选表头

这一行怎么读:Worcester 的 Thorneloe Lodge 诊所,2026 年 8 月开了 1 条 K-Lite 弹力绷带(10 cm × 4.5 m)的处方,共 1 卷,净原料成本 11 英镑,实际成本 9.93 英镑。绷带属于器具,所以化学物质码只有四位(2002 是器具的类目码),呈报形式码只有十一位(20020200822),这与药品类的九位加十五位结构不同。

再看一个药品类的行,取同一份文件里另一家诊所的降压药。

"2026-08","NORTH WEST","NHS GREATER MANCHESTER INTEGRATED CARE BOARD","NHS GREATER MANCHESTER ICB - 02A","02A00","示例诊所名","P88001","M1 1AA","0205051L0","Indapamide","0205051L0AAABAB","Indapamide 2.5mg tablets","02: Cardiovascular System","56.",2,"112.","0.","3.16","2.91","N","3212811000001103"
#-- 该行为结构示意:列数与真实文件一致,机构名与邮编为占位

两行对照能看出三件事。第一,器具行与药品行共用一套列,但编码长度不同,任何按固定长度切分的代码都会在器具行上出错。第二,TOTAL_QUANTITY 由 QUANTITY 与 ITEMS 相乘而来,可以直接用整数记法复算一遍做校验。第三,NIC 与 ACTUAL_COST 是两个口径,前者是基本药价,后者是扣减之后的实际支付,两者差值体现的是折扣与加成,跨年比较必须用同一口径。

2.4 单月规模与分布

用 2026 年 8 月单月的处方成本分析(PCA)文件做全量统计,可以得到这一期英格兰初级保健处方的基本盘。PCA 与 EPD 同源自 NHSBSA 结算系统,但 PCA 按「调配方」汇总、EPD 按「处方者」汇总,两者的行数不同,正好用来说明口径差异。

指标 2026 年 8 月数值 说明
记录行数 518,836 调配方 × 呈报形式 × 区域维度
处方项目总数 103,330,941 约一亿零三百万条项目
净原料成本合计 967.3 百万英镑 约九亿六千七百万英镑
涉及呈报形式 20,550 种 去重后的 BNF 呈报形式码
涉及化学物质 1,780 种 去重后的化学物质码
调配方类型 药房、配药医生、器具承包商、个人给药四类 药房占 328,606 行
最大章节 第二章 心血管系统,3,196 万项目 占全部项目约三成

BNF 章节的分布严重不均。同一月份按项目数排序,前四章(心血管、中枢神经、内分泌、消化)合计超过七千三百万项目,占全部项目的七成以上。这个形状在十余年里相当稳定,心血管系统长期是第一大章,原因是长期用药与人口老龄化两股力量叠加。

BNF 章节 2026-08 项目数(万) 粗略占比
02 心血管系统 3,196 31%
04 中枢神经系统 1,963 19%
06 内分泌系统 1,215 12%
01 消化系统 971 9%
09 营养与血液 587 6%
03 呼吸系统 571 6%
其余十五章合计 1,830 17%

2.5 与同类资源的字段差异

把 EPD 与三种常见的处方数据放在一起比字段,差异一望即知。英国的医院处方(SCMD)按信托与呈现形式给,没有诊所层;美国的 Medicare Part D 按药品与计划给,按年度汇总;北欧登记库有患者级,但要申请。

字段/能力 EPD 与 OpenPrescribing 英格兰医院药品数据 SCMD 美国 Medicare Part D 北欧处方登记库
处方者机构层 有,到 GP 诊所 有,到 NHS 信托 无 有,到开方机构
患者级 无 无 无 有
时间粒度 月 月 年 日到月不等
药品编码 BNF 五级 + SNOMED dm+d 与 SNOMED NDC 与 RxNorm ATC
成本字段 NIC 与实际成本双口径 有,含指示价 有,按计划口径 有限
获取门槛 公开下载 公开下载 公开下载 申请制
许可 OGL-UK-3.0 OGL-UK-3.0 美国政府公开数据 各国不一
覆盖 英格兰初级保健 英格兰二级保健 美国联邦医保 各国自定

这张表解释了一个常见误解:以为「国外也有同样的数据」。有同类数据,但同时满足「诊所级、月度、公开、免费、可商用」的,只有英格兰这一套。

§3 身份层:它到底是什么

3.1 一个 Django 应用,不是一个数据库产品

OpenPrescribing 的软件形态是公开的:GitHub 上的 ebmdatalab/openprescribing 仓库,一个 Django 应用,同时提供 REST API 与仪表板,README 里写明它服务的是「NHS Digital 的 GP 级处方数据」与「NHSBSA 的详细处方信息报告」。站点部署在生产环境的裸机上,测试跑在 GitHub Actions 的容器里。

这个形态决定了它的产品性格。开源意味着方法可审计:任何一个指标怎么算,都能回到代码里找到实现。Django 意味着它天然是一个「按 URL 取数」的系统,每一个图表页都有固定网址,这为引用和复现提供了便利。而「仪表板集群」的架构也意味着它不是一门通用的 SQL 服务——想做大范围的自由查询,仍然要自己下载 CSV。

身份维度 具体表述 对使用者的含义
法律主体 学术机构的研究项目 无商业售卖压力,但依赖资助
软件形态 Django 应用,代码开源 指标可实现审计
服务形态 网站 + REST API + CSV 下载 适配浏览、程序、批量三条路径
数据地位 二手加工方,非原始生产方 上游改了,它跟着改,有时滞
语言 英文界面与英文药品名 中文使用者需自建术语映射
覆盖国家 仅英格兰初级保健 苏格兰、威尔士、北爱须另找

3.2 三条产品线:初级保健、医院、定制分析

平台并非只有一条线。第一条是主线,即初级保健处方,数据来自 EPD,覆盖 GP 与部分非 GP 处方者。第二条是 2021 年之后才有的医院线,数据来自 Secondary Care Medicines Data(SCMD),覆盖 NHS 信托,2024 年有专门论文介绍这个医院侧工具。第三条是服务化的定制分析,为 NHS 机构做专题,成果常见于学术期刊。

三条线共用一个方法论内核:把难用的原始数据变成可比的标准化指标。差别在于维度不同——初级保健按诊所比,医院按信托比,定制分析按委托方关心的问题比。

产品线 数据来源 比较单元 起点 典型用途
初级保健 EPD GP 诊所、PCN、ICB 2014(分析序列可回溯 1998) 用药变异、成本、指南一致性
医院侧 SCMD NHS 信托 2021-07 高价药采纳、剂量强度
定制分析 多源 按委托 按项目 专题评估、政策效果

3.3 名字与域名

「OpenPrescribing」一词在中文语境里常被直译成「开放处方」,读起来像个形容词短语。更准确的读法是把它当成一个产品的专名:开放 + 处方 + 进行时,强调「正在被公开地开具」这一动作本身。域名 openprescribing.net 与产品名一致,.net 而非 .org 或 .uk,早期的项目性质由此可见一斑。

3.4 谁在用

平台方法学论文里提到过一个量级:上线一年就为约五万名使用者提供了超过二十五万次分析。这个数字说的是使用频次,不是用户画像。从后续文献的使用场景反推,主要人群有四类:NHS 内部的质量改进与药事管理岗;学术机构的卫生服务研究者;做药品市场分析的行业分析师;以及少量记者与公众。

第四类值得单独说一句。把处方数据做到「任何一个居民都能查自家诊所」的程度,是一种刻意的公共性设计。它把数据从研究者的工具变成了公民可用的证据,代价是必须承担误读的风险——这也是平台为什么要给每个指标配方法说明。

§4 质量层:它凭什么可信

4.1 来源的单一性与结算的强制性

EPD 的可信度首先来自它不是一个「调查」。调查数据有应答偏差、有回忆偏差、有失访。处方数据不是这样来的:一张处方要拿到药,必须在药房调配,药房要向 NHSBSA 申报才能拿到钱。申报就是记录,记录就是数据。这条链条的强制性,把「漏报」压到了很低的水平。

代价是它只覆盖「走了结算流程」的处方。任何不经过这条链的给药——住院期间的用药、诊所内的即时给药、药房按 PGD 直接供应的药——都不会出现在 EPD 里。所以它是一份「结算口径的完整清单」,不是「全部用药的完整清单」。

属性 表现 对质量的影响
采集方式 结算申报,非调查 应答偏差与回忆偏差极低
覆盖对象 走结算的社区调配处方 住院与 PGD 供应被系统性排除
时间连续性 逐月,十余年不断 适合做时间序列与断点分析
机构归属 由处方者机构代码决定 机构合并会造成序列断裂
编码变更 BNF 与 SNOMED 定期改版 跨年比较需先做映射

4.2 标准化的三个动作

平台在原始数据之上做了三件标准化的事,这三件事构成了「原始 CSV」与「平台指标」之间的差异。

第一件是层级上的统一。原始行的粒度是呈报形式,同一化学物质可能对应几十个呈报形式(不同厂家、不同规格、不同剂型)。平台把呈报形式上卷到化学物质层,让「阿托伐他汀」成为一个可比的单位。这一步的代价是丢掉了规格信息,好处是让跨诊所的比较有了共同基准。

第二件是人口的分母。不同诊所的名单人口差异巨大,单看项目总数毫无意义。平台用每千名登记患者的项目数作为标准率,把规模效应剥掉。这个分母本身也有坑:名单人口含「幽灵患者」,即已搬走或已故但未及时移除的登记,各诊所清理力度不同。

第三件是异常值的识别。平台提供「这个化学物质在本机构是否异常」的排名,方法在 2023 年的 JMIR 论文里公开:对每个化学物质计算本机构与同侪的偏离程度,再按偏离排序。这套方法是无假设的——先扫全量,再挑出值得看的部分,而不是先设定议题。

标准化动作 输入 输出 损失了什么
呈报形式上卷 15 位呈报形式码 9 位化学物质码 规格与剂型细节
人口标准化 项目数 + 名单人口 每千患者项目数 名单人口本身的误差
异常值排序 各机构标准率 偏离排名与分位 排序不等于临床意义

4.3 多篇独立论文的使用与复核

一套数据能不能信,一个务实指标是它被多少独立研究用过、有没有被复核出系统性错误。以 Europe PMC 检索「OpenPrescribing」,得到 136 条命中,其中标题里直接出现该词的论文有 4 篇:2018 年的方法学论文、2023 年的异常值识别论文、2024 年的处方时长论文、2025 年针对医院侧的介绍论文。围绕它做的应用研究则覆盖抗精神病药趋势、阿哌沙班逆转剂使用、抗癫痫药妊娠风险、糖尿病持续血糖监测可及性、低优先级药品干预试验等方向。

这些研究本身就是一种外部验证。如果底层数据有系统性缺陷,跨药品、跨地区、跨年份的大量研究会在同一类结论上撞墙。至今公开文献里最常见的抱怨不是「数字不对」,而是「口径复杂、需要大量领域知识才能用」——这恰好印证了平台的定位:它降低门槛,但没有消灭门槛。

4.4 案例:Saltaire 与 Windhill 合作诊所的一张处方账

用一家真实的诊所把上面的抽象讲透。B83039,Bradford 的 The Saltaire & Windhill Medical P’ship,属于西约克郡 ICB,邮编 BD18 1QB。在 2026 年 8 月单月文件里,这家诊所有 289 行记录,合计 4,856 个项目,实际成本 35,567.22 英镑。

拆到章节,它的形状很不寻常:消化系统 3,407 项,心血管 846 项,器具 398 项,造口用品 163 项。第六章的占比高得离谱。继续下钻到化学物质层,第一名是兰索拉唑(0103050L0)2,550 项,第二名是吲达帕胺(0202010P0)437 项,第三名是呋塞米 370 项;而实际成本的第一名是「间质液葡萄糖检测传感器」(器具码 2148),193 个项目花了 14,852 英镑,单项均价约 77 英镑。

import csv

path = "epd_snomed_202608.csv"
target = "B83039"
rows = []
with open(path, encoding="utf-8", newline="") as f:
    for r in csv.DictReader(f):
        if r["PRACTICE_CODE"] == target and r["ITEMS"]:
            rows.append(r)

items = sum(float(r["ITEMS"]) for r in rows)
cost = sum(float(r["ACTUAL_COST"] or 0) for r in rows)
print(len(rows), int(items), round(cost, 2))

#-- 按化学物质聚合,看谁在撑起这家诊所的处方量
agg = {}
for r in rows:
    k = r["BNF_CHEMICAL_SUBSTANCE_CODE"]
    a = agg.setdefault(k, [0, 0.0, r["BNF_CHEMICAL_SUBSTANCE"]])
    a[0] += float(r["ITEMS"])
    a[1] += float(r["ACTUAL_COST"] or 0)
for k, (n, c, name) in sorted(agg.items(), key=lambda x: -x[1][0])[:5]:
    print(k, name, int(n), round(c, 2))
#-- 输出:5 个化学物质的码、名、项目数与成本

这个案例的价值在于展示「异常」不等于「问题」。兰索拉唑占比高,可能是因为这家诊所服务的人群里消化不良就诊多,也可能是长期抑酸治疗的存量患者集中;传感器项目数少而成本高,是因为它单价高、按人头配发。单看排名会把这家诊所标成「消化系统异常」,但同一份数据也能给出第二种解释:它的造口与器具占比同样偏高,说明人群构成可能不同。

这正是 §4.4 的案例要说明的方法论立场:排名是提问的起点,不是结论。要判断它是否真的异常,至少还要做三件事——拉出三年的序列看是持续偏高还是单月跳变;对比同 PCN 的其他诊所;用平台给出的每千患者标准率而不是绝对数。任何一步都不能省。

同样的逻辑适用于后面的取数章节。§4.4 的案例在 §5 里会再用一次,用 API 端点验证平台的数字与 CSV 一致;在 §7 里第三次出现,用来演示什么是「把小样本反推当证据」的错误。

4.5 覆盖的盲区清单

把已知的排除项列全,比笼统地说「有局限」有用。NHSBSA 的发布说明里逐条写明了这些排除,做研究时应当逐条核对是否影响结论。

盲区 是否在 EPD 内 影响
住院期间给药 否 无法看院内用药强度
医院站点码处方 否 部分院外延续处方丢失
医院成本中心处方 是 与上一条相反,需注意不对称
牙科处方 否 口腔科用药不全
药房 PGD 供应 否 Pharmacy First、避孕、戒烟、流感疫苗缺失
私人处方 极有限 仅「私方」标记部分
苏格兰、威尔士、北爱处方 否 仅英格兰开具
威尔士、苏格兰、属岛调配 是 英格兰开具、异地调配仍计入

最后一行容易被忽略:数据的地理口径是「英格兰开具」,不是「英格兰调配」。一张英格兰诊所开的处方,病人拿去威尔士的药房取药,仍然算在这家诊所头上。做地区对比时,分子按处方地、分母按登记人口,两者地理口径不同,会在边境地区引入偏差。

§5 取数层:三条路,各有各的取舍

5.1 路径一:平台图表页,零门槛但受页面结构约束

最省事的用法是直接用网站。输入药品名或诊所名,平台给出时间序列、机构排名、同侪分位。每张图都有固定网址,可以直接引用,也可以贴进报告。

这条路的天花板也很清楚。图表页是给浏览器渲染的,程序化抓取会碰到前端渲染与访问防护两道墙。2026 年 10 月对 openprescribing.net 的三个入口(主站、/api/、/data/)发起普通 HTTP 请求,返回的都是 403 与 Cloudflare 的挑战页,而不是内容。这不代表站点不可用——浏览器正常访问没有问题——但意味着批量化取数不应依赖网页抓取。

优点 缺点 适合谁
零配置、零代码 无法批量取数 临床药师、记者、公众
指标已算好 指标口径固定,不能自定义 需要快速答案的人
有固定网址可引用 大批量抓取会被拦 写报告、写报道的人
附方法说明 英文界面 能读英文的使用者

5.2 路径二:REST API,适合点查询

平台的 REST API 按版本号组织,路径形如 /api/1.0/<端点>/。已知的端点族包括 spending(某药品在某机构的支出)、org_details(机构的人口与基础属性)、bnf_code(BNF 代码的检索与层级)、price_per_unit(单价序列)。响应格式支持 JSON,部分端点不需要密钥。

下面的脚本演示一个典型查询:取某个 BNF 化学物质在某家诊所的逐月支出。因为接口参数会随版本调整,脚本先做参数探测,再按实际可用参数重试,避免硬编码失效。

#-- 先探一次接口是否可达,打印状态码与内容类型
curl -sS -o /dev/null -w "%{http_code} %{content_type}\n" \
  "https://openprescribing.net/api/1.0/spending/?code=0212000Y0&org_type=practice&org=B83039&format=json"

#-- 返回 200 则直接落盘;返回 403 说明被访问防护拦下,改走 5.3 的全量 CSV
curl -sS -L "https://openprescribing.net/api/1.0/spending/?code=0212000Y0&org_type=practice&org=B83039&format=json" \
  -o spending_b83039.json
import json
import urllib.request

BASE = "https://openprescribing.net/api/1.0"


def get(endpoint, params):
    url = BASE + endpoint + "?" + "&".join(f"{k}={v}" for k, v in params.items())
    req = urllib.request.Request(url, headers={"Accept": "application/json"})
    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.loads(resp.read().decode("utf-8"))


#-- 机构基础属性:名单人口是标准率的分母
org = get("/org_details/", {"org_type": "practice", "org": "B83039", "keys": "total_list_size"})
print(org)

#-- 药品支出序列:code 用 9 位化学物质码,org_type 可为 practice / CCG / STP
spend = get("/spending/", {"code": "0212000Y0", "org_type": "practice", "org": "B83039"})
print(len(spend), spend[0] if spend else None)
#-- 若报 403,说明当日防护策略变化,改用 5.3 的多月 CSV 自行聚合

API 的取舍是:查询快、参数语义清楚、不用下载几 GB;但只能取回平台已经算好的指标,不能做平台没提供的交叉。而且它依赖平台的可用性——一旦防护策略收紧,程序化调用会先受影响。

端点 用途 关键参数 返回
/api/1.0/spending/ 某药品的支出序列 code、org_type、org 按月的成本与数量数组
/api/1.0/org_details/ 机构人口与属性 org_type、org、keys 名单人口、机构类型
/api/1.0/bnf_code/ BNF 代码检索 q(名称或码)、type 匹配的码与层级名
/api/1.0/price_per_unit/ 单价序列 code、org_type 按月单价

5.3 路径三:上游全量 CSV,适合复算

真正要「说清一个数字是怎么来的」,只能走这条路。NHSBSA 开放数据平台跑的是 CKAN,接口稳定且无需密钥。取一个月的流程分三步:按数据集名拿资源清单,挑出目标月份的资源,下载。

#-- 第一步:取数据集元数据,拿到全部资源列表
curl -sS "https://opendata.nhsbsa.net/api/3/action/package_show?id=english-prescribing-dataset-epd-with-snomed-code" \
  -o epd_package.json

#-- 第二步:列出资源名与体积,确认要哪一个月
python3 -c "
import json
d = json.load(open('epd_package.json'))['result']
for r in d['resources'][-3:]:
    print(r['name'], r['size'], r['url'])
"
import csv
import json
import urllib.request


def resources(dataset):
    url = "https://opendata.nhsbsa.net/api/3/action/package_show?id=" + dataset
    with urllib.request.urlopen(url, timeout=60) as resp:
        return json.loads(resp.read().decode("utf-8"))["result"]["resources"]


def download(url, path):
    #-- 上游会 302 到对象存储,urllib 默认跟随重定向
    with urllib.request.urlopen(url, timeout=900) as resp, open(path, "wb") as f:
        while True:
            chunk = resp.read(1 << 20)
            if not chunk:
                break
            f.write(chunk)


rs = {r["name"]: r for r in resources("english-prescribing-dataset-epd-with-snomed-code")}
r = rs["EPD_SNOMED_202608"]
print(r["size"], r["url"])
download(r["url"], "epd_snomed_202608.csv")
#-- 全量约 7.4 GB,建议先确认磁盘余量与是否已有 zip 镜像

文件到手之后,第一个要养成的习惯是先不做任何聚合,先数行、数诊所、数空值。这一步能立刻暴露编码或解析问题。下面这段脚本就是做这件事的。

import collections
import csv

path = "epd_snomed_202608.csv"
n = 0
practices = set()
icbs = set()
nulls = collections.Counter()
chems = set()
with open(path, encoding="utf-8", newline="") as f:
    reader = csv.DictReader(f)
    for r in reader:
        n += 1
        practices.add(r["PRACTICE_CODE"])
        icbs.add(r["ICB_CODE"])
        chems.add(r["BNF_CHEMICAL_SUBSTANCE_CODE"])
        for k, v in r.items():
            if v in ("", None):
                nulls[k] += 1
print("行数", n, "诊所", len(practices), "ICB", len(icbs), "化学物质", len(chems))
print("空值最多的五列", nulls.most_common(5))
#-- 用整月文件跑,行数应与官方描述的量级相当(千万行级别)

5.4 字节区间抽样:不下载全量也能看清结构

做结构核对不必把七 GB 拖下来。HTTP 的 Range 请求允许只取文件头部若干兆字节,对于以行为单位、按字母序排列的 CSV 来说,头部足以看清列名与首几十行,也足以验证解析器写得对不对。

#-- 只取前 2 MB,够看清表头与前几百行
curl -sSL -r 0-2000000 -o head_202608.csv \
  "https://opendata.nhsbsa.net/dataset/906115a6-4155-44be-8b81-f8e83cebfb84/resource/30b74257-9912-4b54-8990-8eec2a4b7f14/download/epd_snomed_202608.csv"

head -1 head_202608.csv
wc -l head_202608.csv
#-- 注意:区间截断会把最后一行切成半行,统计时必须丢掉末行

用这种方式取到 2 MB 时,实际得到 4,834 行完整记录,涵盖 30 家诊所、15 个 ICB、六个英格兰区域与 270 个化学物质。这 30 家的项目数从一千五百多到四千八百多不等,合计 35,632 个项目、23 万余英镑,人均中位数约一千二百个项目。

抽样段规模 行数 诊所 ICB 化学物质 用途
前 2 MB 4,834 30 15 270 结构核对、解析器调试
全量单月 一千七百万级 六千余 42 一千七百余 正式统计、排名复算

5.5 BNF 编码:一份数据里最需要先弄懂的语法

EPD 的所有药品识别都建立在 BNF 编码上。这套编码既简单又容易被误解:它简单在纯粹是位置化的前缀分层,容易被误解在「九位」这个说法只对药品成立,器具是四位。

九位药品码的分层如下。以 0212000Y0 为例:02 是章(心血管系统),12 接着是节(高脂血症用药),000 是段的具体编号,合起来 0212 是节、021200 是段,Y 是化学物质的序号。这个码指向的化学物质是 Atorvastatin,中文药名阿托伐他汀。同一化学物质下还会有 AA 产品码与四位呈报形式码,拼成十五位才能精确到「某规格某剂型」。

层 字符位置 长度 例子 含义
章 Chapter 1–2 2 02 心血管系统
节 Section 1–4 4 0212 高脂血症用药
段 Paragraph 1–6 6 021200 降脂药(段内分类)
化学物质 Chemical 1–9 9 0212000Y0 阿托伐他汀
产品 Product 1–11 11 0212000Y0AA 某厂家规格组
呈报形式 Presentation 1–15 15 0212000Y0AAABAB 10mg 片剂某一包装

这个分层结构在 BNF 官方码表里是一张扁平表,每一行给出一套完整的「章名、节名、段名、化学物质名、产品名、呈报形式名」。2026 年 9 月版本 90 的码表有 55,589 行,对应 21 个章、222 个节、504 个段、616 个亚段、3,000 个化学物质码、35,516 个产品码与 55,589 个呈报形式码。其中 26,114 行是器具类(四位化学物质码 + 十一位呈报形式码),29,475 行是药品类(九位 + 十五位)。

import csv

#-- 按月取最新一版 BNF 码表:chapter/section/paragraph/chemical/product/presentation 六列齐全
path = "bnf_code_current_202609_version_90.csv"
levels = {"chapter": set(), "section": set(), "paragraph": set(), "chemical": set(),
          "product": set(), "presentation": set()}
with open(path, encoding="utf-8-sig", newline="") as f:
    for r in csv.DictReader(f):
        levels["chapter"].add(r["BNF_CHAPTER_CODE"])
        levels["section"].add(r["BNF_SECTION_CODE"])
        levels["paragraph"].add(r["BNF_PARAGRAPH_CODE"])
        levels["chemical"].add(r["BNF_CHEMICAL_SUBSTANCE_CODE"])
        levels["product"].add(r["BNF_PRODUCT_CODE"])
        levels["presentation"].add(r["BNF_PRESENTATION_CODE"])
print({k: len(v) for k, v in levels.items()})

#-- 用九位码反查层级:截取前缀即可,不需要连表
code = "0212000Y0"
print(code[:2], code[:4], code[:6], code)

平台侧还提供了一个 bnf_code 端点,作用是把「名字」与「码」互相翻译。它的实用价值在于模糊匹配:输入「atorvastatin」能返回该化学物质及其下属呈报形式的码,省掉手工查表。

你想知道 用哪一层 为什么
这家诊所总共开了多少药 章 章是最大粒度,适合看结构
抗菌药使用强度 节 0501 抗菌药集中在第五章第一节
某一类药的具体品种分布 化学物质 跨厂家可比
原研与仿制的比例 产品或呈报形式 只有这一层能区分品牌
某个剂量的使用 呈报形式 规格写在呈报形式里

5.6 与人口数据的连接

标准化率的分母来自机构名单人口。这个数字不在 EPD 里,需要从别处取。平台提供了 org_details 端点,返回机构类型与名单人口;若要更细的人口结构(年龄、性别、贫困指数),得去 NHS England 的公开文件或 ONS 的中层超级输出区数据。

连接的关键是代码对齐。GP 诊所代码(如 M81037)是稳定主键,可以用它连平台、连 NHS England、连 ONS 的地区表。ICB 代码在不同时期的写法有微妙差别(36J00 与 36J),在连接前必须统一到同一层级,否则会出现大量匹配失败。

#-- 取一家诊所的名单人口,作为每千患者标准率的分母
curl -sS "https://openprescribing.net/api/1.0/org_details/?org_type=practice&org=B83039&keys=total_list_size" \
  -o org_b83039.json
cat org_b83039.json
#-- 若返回 403,改为从 NHS England 的诊所名单文件取同一字段

§6 与库内相关记录的关系

6.1 关系图谱

英国来源在中文数据集库里长期偏薄,能拿得出手的多是影像与基因组,公共卫生与处方方向几乎空白。OpenPrescribing 补的正是这一块:它不是患者队列,也不是医院事件,而是「社区用药」这个中间层。

库内记录 与 OpenPrescribing 的关系 能否直接连接 连接键
NHS HES 互补:HES 记医院事件,此处记社区用药 部分可,需地区代码 地区代码、机构代码
QResearch 对照:QResearch 有患者级 Read 码,此处没有 不可直接连 无
UK Biobank 极少交集 不可 无
英国十万基因组计划 无交集 不可 无
Genomics England 相关记录 无交集 不可 无
药物安全类记录(如 FAERS 类) 互补:一个看用药量,一个看不良事件 概念层可连,行层不可 ATC 或药名映射
药物-靶点类记录 提供药品名单的上游参考 可做名词映射 药名、BNF 段

这张表最该读出的一句话是:OpenPrescribing 与 QResearch 在「同一批诊所、同一批患者」上重叠,但两者是两种完全不同的数据。QResearch 里能看到某位患者的 BMI、血压、诊断与处方,OpenPrescribing 里只能看到这家诊所一共开了多少。想做个体研究走前者,想做群体对比走后者。

6.2 检索路径

在库里找「跟处方有关的英国数据」,有三条入口。按来源找:source 含 NHSBSA 或 Oxford 的名字。按标签找:公共卫生与流行病学 加 真实世界数据 的组合,命中的多是枢纽页。按编码找:任何提到 BNF 的名字,OpenPrescribing 是其中唯一以 BNF 为组织核心的。

检索意图 关键词 预期命中 说明
英国处方数据 处方、prescribing、BNF 本篇 库内目前唯一
英国医院活动 HES、住院、episode NHS HES 事件级
英国初级保健患者级 QResearch、Read 码、EMIS QResearch 申请制
药物不良事件 不良事件、FAERS、Yellow Card 药物安全类 结局侧
药品编码体系 BNF、ATC、dm+d 本篇与药物类 编码侧

6.3 与医院侧数据的接力

一个典型的多源研究是这样接力的:先用 OpenPrescribing 看某药在社区的开具量上升,再用医院侧数据看同一药在信托的使用量,最后用不良事件数据看结局。三步各自独立,靠药名或编码对齐。OpenPrescribing 在链条里扮演「最早发生、覆盖面最广」的那一环——社区处方往往先于医院使用量变化,因为多数慢病药是从社区开出的。

这条接力也说明了它的生态位:它不是研究链条的终点,而是入口。所有以它起手的研究,最终都要接到另一个数据源上才有结论。

§7 质量评估与局限性

7.0 阅读本节前的一个前置校正

在给这份数据打分之前,必须先纠正一个常见的错位:很多人拿「数据集」的尺子去量一个「平台」,然后因为它没有患者级链接、没有诊断字段而判它低分。这是误判。评价 OpenPrescribing 的正确尺子,是「在处方行为这个特定切面上,它做得有多好」,而不是「它能不能替代一个临床数据库」。

同样的误判还有一个变体:拿「数据准确性」去质疑它,说某家诊所的数字看起来不对。这类质疑大多不是数据错,而是口径没对齐——处方时长不同、名单人口含幽灵患者、机构合并沿用旧码。把这三件算清楚再比,绝大多数「不对」会自动消失。§4.4 的案例里那家诊所的「消化系统异常」,就是典型的口径产物而非错误。

7.1 五维评分

下面这套评分借用了数据质量评估常用的五维框架,按「它在自己的定位上做得如何」打分,而不是按「它有多像临床数据库」打分。

维度 分数(5 分制) 依据
完整性 Completeness 4.5 结算口径全覆盖,排除项明确列出
准确性 Accuracy 4.0 结算驱动,错误率低;折扣算法 2024 年变更
一致性 Consistency 3.5 编码与机构层级多次变更,跨年需映射
时效性 Timeliness 3.5 月度更新,滞后约两月
可用性 Usability 5.0 免费、开放、有 API、有下载、有方法文档
可链接性 Linkability 3.0 机构层可连,患者层不可连

可用性给满分是有理由的:同时做到免费、免申请、有 REST API、有全量下载、有公开方法文档、有开源代码的处方数据源,全球找不到第二个。可链接性给低分同样有理由:它只能向外连到机构层,不能连到个体,这限制了它在多源融合研究中的角色。

7.2 DAIMS 六维评估

DAIMS 是一套面向「数据供给方与使用方之间契约」的评估框架,六个维度分别问:数据是否被描述清楚、质量是否被声明、使用是否有条件、供应是否可持续。把它套在 OpenPrescribing 上,能看出它的强项与短板分布得很不均。

DAIMS 维度 评分(5 分制) 具体表现
数据描述 Data Description 5 字段字典、数据集说明、码表、方法论文齐备
数据质量 Data Quality 4 排除项逐条列明;折扣算法有过一次断点
数据访问 Data Access 5 免申请、免密钥、API 与批量下载并存
数据使用 Data Use 5 OGL-UK-3.0 允许商用,条款清晰
数据标识 Data Identification 4 数据集名与版本号稳定;资源 ID 会变,需按名匹配
数据供给 Data Provision 4 月度节奏稳定;依赖学术资助,长期存续有不确定性

六项里有三项满分。数据访问与数据使用两项满分,是它区别于绝大多数「需要签协议才能用」的卫生数据的根本。数据描述满分,是因为它不只给了字段名,还给了每个字段为什么要这样定义。真正扣分的地方在供给侧:一个学术项目即便做得再好,其存续仍取决于资助周期,这是所有公共品型基础设施的共同软肋。

把这张表与 7.1 的五维评分对照着看,有一个结论很稳:它的短板几乎都在「能不能连到个体」这一侧,长处几乎都在「能不能免费拿到并用起来」这一侧。选它做研究,就是选了这个取舍。

7.3 治理与披露控制

即便只有聚合数据,隐私问题也没有消失。原因在于「聚合」不等于「无法反推」。设想一个化学物质在某个小诊所只有两三个项目,若同时知道该诊所的名单人口很小、且该药只用于一种罕见适应症,那么这两三个项目就可能指向具体的个体。这类风险在小分母、低频次、高特异性的交叉格上最突出。

NHSBSA 对此有披露控制规则:公开文件的层级是机构,不再往下拆;对极小单元格的处理依赖统计披露控制的一般原则(最小单元格阈值与二次抑制)。使用者在做二次分析时,如果自己按更细的维度切片(比如机构 × 邮编 × 罕见药),就相当于绕开了这一层保护,必须自行判断是否越界。

风险类型 触发条件 缓解方式 使用者该做什么
小分母反推 诊所名单人口小 + 低频特异药 不提供患者层;机构层聚合 切片前先看分母
罕见药唯一性 某药全国只有少数患者 呈报形式上卷 避免在机构层发布罕见药明细
医生可识别 单人诊所 + 处方风格独特 只到机构层 不把机构异常归因到个人
再识别链接 与外部名单人口数据连表 机构代码本身是公开的 连表后不再发布个体层结果
商业敏感 单一厂家份额 平台不提供厂家级明细 需要厂家分析时自建映射

第二行值得强调。某些药在英格兰全国的使用者可能只有几百人,分到六千家诊所后,多数诊所是零。若某诊所出现 1 个项目,这个项目背后大概率只有一位患者。发布「某诊所开了 1 次某罕见药」这种表述,在统计上就等于公布了那位患者的存在。

7.4 已知的、可枚举的偏差

把偏差一条条列出来,比说「数据有偏差」有用。下面每一条都能在官方文档或方法学论文里找到出处。

偏差 机制 方向 影响谁
处方时长偏差 28 天与 56 天处方并存,项目数差近一倍 系统性高估短周期诊所 所有跨诊所比较
名单人口偏差 幽灵患者未清理,各所力度不同 高估分母,低估标准率 每千患者指标
机构合并偏差 合并后沿用旧码,序列在合并月跳变 单月异常 时间序列分析
编码漂移 BNF 改版导致化学物质归类迁移 跨年不可直接相加 长期趋势
成本算法断点 2024 年 4 月起折扣算法变更 实际成本跳变 成本序列
折扣未反映 实际成本是平均折扣后的值 个体差异被抹平 精细成本分析
非 GP 处方者混入 门诊、监狱、诊所内服务同表 机构层面异质 诊所排名
地理口径错配 分子按处方地、分母按登记地 边境地区偏差 地区对比

处方时长那条最容易被低估。MacKenna 等人用 2018 年 12 月至 2019 年 11 月的 12 个月数据算过,全部片剂与胶囊里 48.5% 来自 28 天处方,总量约二十五亿片。这意味着「一个患者一年的项目数」在两种诊所之间可以差到接近两倍,而这个差异与临床质量毫无关系。

7.5 外部验证矩阵

一份数据被外部验证到什么程度,可以用一张矩阵表达。左侧是验证类型,右侧是具体证据。

验证类型 具体证据 结论
方法学论文 BMJ Open 2018,Curtis 与 Goldacre 数据处理与归一化方法公开
异常值方法 JMIR 2023,6,500 家诊所 6 个月数据 无假设异常值识别可行
干预评估 BMC HSR 2025,40 个 CCG 随机 可用作临床试验的结局数据源
长期趋势 多篇药物类别趋势研究 序列连续性可支撑十年尺度
医院侧扩展 2024 与 2025 年医院工具论文 方法可复制到二级保健
跨国对照 爱尔兰 RxTrends 类工具 思路被其他国家借鉴
政策影响 低优先级药品、甲氨蝶呤等项目 支撑过国家级质量改进

七类验证里有六类是「用它做研究并发表」,一类是「方法被复制」。这种验证结构说明它在学术共同体内已被接受为默认工具之一,但也提醒:验证的是「能用来做研究」,不是「数字绝对无误」。

7.6 它为何能持续:结算制度每年白送一份全量账本

一份公开数据能活十几年,靠的从来不是情怀。OpenPrescribing 的生存逻辑有三层,每一层都嵌在英格兰的卫生制度里。

第一层是数据供给的零成本。处方数据不是为研究专门采集的,它是 NHSBSA 结算流程的副产品。只要英格兰还有社区药房按处方结算,这份账本每个月就会自动产生一次。上游不需要为「开放」额外付采集成本,开放只是把已有产物多复制一份。这是最硬的一层:制度在,数据就在。

第二层是使用方的分散与刚性。NHS 内部的质量改进、ICB 的季度报告、学术机构的论文、记者的调查,四类需求分散在不同机构,但都指向同一份数据。任何一方单独建设都不划算,共享一个平台则成本极低。平台因此获得了一种「公共品」的地位——没人能独占它,也就没人有动机把它关掉。

第三层是资助的多元。项目长期依赖Wellcome、国家健康研究院与大学自有经费的组合,以及面向 NHS 机构的服务收入。这种组合让它在单一资助方撤出时不至于停摆,代价是必须持续证明「有用」——所以它要发论文、要出案例、要维护 API。

三层叠起来,就是一个自我维持的循环:制度产数据,数据引使用,使用证价值,价值换资助,资助保平台。§4.4 的案例之所以值得反复引用,正因为它同时展示了这个循环的两端:一家普通诊所的月度账本,和一个可以被任何人复查的公共事实。

§8 生态位与历史

8.1 从「月度大文件」到「可查询的账本」

时间线要从 2011 年算起。那一年英格兰开始按月公开 GP 级处方数据,最初的形态是 NHS 信息服务门户上的一份份文件,研究者下载后自行处理。2014 年起,英文处方数据集(EPD)的前身开始以更结构化的形式发布,覆盖 2014 年 1 月及以后。

2015 年前后,牛津的 EBM DataLab 把「让数据可被提问」做成了一个项目,openprescribing.net 上线。2018 年,团队在 BMJ Open 发表方法学论文,把 1998 至 2016 年的年度处方成本分析(PCA)数据做了归一化,解决了药品名与分类随时间漂移的问题。这篇论文的定位很清楚:先解决「历史序列能不能拼起来」,再谈分析。

时间 事件 意义
2011 英格兰开始按月公开 GP 级处方数据 数据供给起点
2014-01 EPD 前身覆盖起点 现有可下载的最早月份
2015 前后 openprescribing.net 上线 从文件走向查询
2018 BMJ Open 方法学论文 归一化方法与工具说明
2020-03 NHSBSA 在开放数据平台建立 EPD 数据集 下载入口标准化
2021-02 EPD with SNOMED 起 编码体系双轨
2021-07 医院侧 SCMD 数据起 二级保健补齐
2022-07 CCG 改为 ICB 机构层级大改
2024 医院侧工具论文 方法复制成功
2025 旧版 EPD 标注退役 历史数据统一到新版

8.2 机构层级的两次大改

第一次是 2013 年,初级保健信托(PCT)被撤销,临床委托组(CCG)登场。第二次是 2022 年 7 月,CCG 被整合照护委员会(ICB)取代,数量从一百多个收缩到四十二个。两次改动都在数据里留下了痕迹:字段名从 PCT 变成 CCG 再变成 ICB,代码体系整批更换。

对使用者的直接影响是:任何跨 2022 年 7 月的地区对比,都必须先建立「旧 CCG → 新 ICB」的映射。平台自己也做了这层映射,所以图表页上的地区序列是连续的;但如果自己下载原始 CSV 拼接,就必须重做一遍。

时期 委托机构 数量级 数据字段
2013 前 初级保健信托 PCT 一百五十余 PCT
2013–2022.06 临床委托组 CCG 约两百 CCG / PCO
2022.07 起 整合照护委员会 ICB 四十二 ICB / PCO

8.3 编码体系的双轨化

2021 年 2 月起,EPD 在 BNF 之外增加了 SNOMED CT 编码与 dm+d 标识。这不是要取代 BNF,而是补一个互操作层:BNF 面向处方分析与药品分类,dm+d 面向药房系统与供应链。两套编码并存,意味着同一条记录可以按两种体系被检索。

双轨也带来一个问题:两套编码并非一一对应。一个 BNF 呈报形式可能对应多个 dm+d 包装,一个 dm+d 包装也可能随时间改挂 BNF 码。NHSBSA 专门维护了一份 BNF 与 SNOMED 的映射表,发布节奏与 EPD 对齐。做精确到包装的分析时,必须用这份映射,不能假设码与码之间天然一致。

编码体系 面向 粒度 起始
BNF 处方分析与分类 化学物质到呈报形式 全程
SNOMED CT 临床术语互操作 概念 2021-02 起
dm+d 药房系统与供应链 包装 2021-02 起

8.4 从初级保健走向二级保健

2021 年 7 月起,二级保健药品数据(SCMD)开始发布,形态与 EPD 类似但单元是 NHS 信托。2024 年,团队发表论文介绍基于它的医院侧工具;2025 年又有专门论文详述平台设计。医院侧的规模远小于社区,但填补了一个关键空白:高价药的院内使用。

两条线合并之后,平台覆盖了英格兰药品使用的主要场景——社区开出的慢病药,与医院使用的注射剂、肿瘤药、生物制剂。两者的比较单元不同(诊所对信托),方法学相同,这正是「一套方法复制到两个场景」的典型样本。

对比项 初级保健线 医院侧线
数据源 EPD SCMD
起点 2014-01 2021-07
比较单元 GP 诊所 NHS 信托
主要药品 慢病口服药 注射剂与高价药
规模 每月千万行级 每月十万行级

§9 使用指引

9.1 三种角色的路径

不同角色该做的事情差别很大,下面按「你要交什么」来分,而不是按「你是什么职称」来分。

角色 你要交的东西 最短路径 要避开什么
临床药师或药事管理者 一份本机构的用药分析 图表页找分位,取同侪序列做对照 不要用绝对数排名
卫生服务研究者 一篇可复现的论文 全量 CSV + 自行聚合,方法写清 不要混用 PCA 与 EPD 口径
卫生经济分析师 一套成本基线 NIC 与实际成本双口径并列 不要在 2024 年 4 月前后直接连
数据工程师 一条稳定的取数管道 CKAN 元数据 + 按月增量下载 不要写死资源 ID
记者或科普作者 一个可核对的数字 图表页取数,附上游链接 不要把项目数说成人次
政策研究者 一次干预前后的对比 设计断点,用月度序列 不要忽略处方时长变化

9.2 一条最短的可用流程

如果只做一次分析,下面这条流程最短:先用 API 或图表页确认方向,再用上游 CSV 复算,最后与同侪对比。全程不需要申请任何权限。

#-- 1. 元数据:确认目标月份的资源存在,并取到下载地址
curl -sS "https://opendata.nhsbsa.net/api/3/action/package_show?id=english-prescribing-dataset-epd-with-snomed-code" \
  | python3 -c "
import json, sys
d = json.load(sys.stdin)['result']
r = [x for x in d['resources'] if x['name'] == 'EPD_SNOMED_202608'][0]
print(r['url'])
"

#-- 2. 抽样:先取前 2 MB 验证解析器
curl -sSL -r 0-2000000 -o head.csv "<上一步输出的地址>"

#-- 3. 全量:确认无误后下载整月文件
#-- 全量约 7.4 GB,建议在磁盘余量充足时执行
import csv

#-- 4. 复算:同一化学物质在一家诊所的月度项目数与成本
target_practice = "B83039"
target_chem = "0103050L0"
items = 0
cost = 0.0
with open("epd_snomed_202608.csv", encoding="utf-8", newline="") as f:
    for r in csv.DictReader(f):
        if r["PRACTICE_CODE"] != target_practice:
            continue
        if r["BNF_CHEMICAL_SUBSTANCE_CODE"] != target_chem:
            continue
        items += int(float(r["ITEMS"] or 0))
        cost += float(r["ACTUAL_COST"] or 0)
print(items, round(cost, 2))
#-- 结果应与平台图表页同月同诊所同化学物质的数字一致,差额在舍入范围内

9.3 引用方式

引用分两种场景。第一种是引用平台,按 NHSBSA 的官方格式写,包含访问日期与网址;第二种是引用数据文件,写清数据集名、月份、许可。如果打算发布基于数据的报道或新闻稿,官方要求先联系其传播团队,目的是避免数字被误读误述——这不是审查,是核实。

引用对象 建议格式 备注
平台 牛津大学 EBM DataLab. OpenPrescribing. 访问日期. 网址 指标页建议附具体 URL
数据文件 NHSBSA. English Prescribing Dataset (EPD) with SNOMED Code, 2026-08. 许可 OGL-UK-3.0 必须含月份
码表 NHSBSA. BNF Code Information, Version 90, 2026-09 版本号不可省
方法学 Curtis HJ, Goldacre B. BMJ Open 2018;8:e019921 DOI 10.1136/bmjopen-2017-019921
再发布 须标注「NHSBSA Copyright」 OGL 条款要求

§10 AI 使用声明

事项 声明内容
本文的写作方式 由 AI 辅助起草,事实性数字均经人工逐项核对
数据获取方式 全部数字来自 NHSBSA 开放数据平台与 Europe PMC 的公开接口
未覆盖的部分 平台网页内容因访问防护未能程序化读取;相关描述依据官方仓库与论文
数字口径 未标注者均为 2026 年 8 月或最近的官方发布月
可复算性 附录 A 列出每项数字的来源与是否可自行复算
已知局限 抽样统计基于单月部分文件,非全量
使用建议 引用前请按附录 A 重新核对目标月份的最新数字
责任边界 本文不构成对任何具体机构或个人的处方质量评价

常见误读

常见说法 实际 证据
「OpenPrescribing 就是 EPD」 平台建在 EPD 之上,EPD 是上游原始数据 平台以 EPD 为数据源,二者许可相同、层级不同
「项目数就是患者数」 项目数是处方条数,一个患者可对应多次 字段定义为「产品出现在处方上的次数」
「可以用它算患病率」 无诊断字段,只能算处方强度 字段表无任何诊断列
「六千家诊所,所以是普查」 覆盖的是处方开具机构,非人口普查 机构层聚合,无患者标识
「数字实时」 月度更新,滞后约两月 官方说明一月的数在三月发布
「全英国都覆盖」 只限英格兰开具 地理范围明确写英格兰
「小诊所的数字可以随便拆」 小分母低频率格存在反推风险 披露控制规则与最小单元格原则
「同一种药,A 诊所开得多是质量差」 多数差异来自处方时长与人群构成 28 天处方占片剂胶囊的 48.5%
「少了药房直接给的药,数据就不完整」 官方明确排除 PGD,但排除项是公开的 五个 PGD 服务被逐条列出
「排名可以直接拿来考核医生」 公布层级止于机构 最低公布单元是处方者机构

FAQ

Q1:OpenPrescribing 和 NHSBSA 的 EPD 是什么关系?
EPD 是 NHSBSA 每月发布的原始处方明细,OpenPrescribing 是建在它之上的查询与对比平台。前者给文件,后者给接口、图表、排名与标准化指标。两者许可同为 OGL-UK-3.0,可以自由下载与再发布,但再发布时须保留版权标注。

Q2:能不能从这份数据算某病的发病率?
不能。数据里没有诊断、没有适应症、也没有患者标识,只有处方项目数与花费。能算的是处方强度,例如每千名登记患者的项目数;不能算的是患病率。任何把它当发病率分母的用法,都会系统性高估或低估。

Q3:为什么同一种药在不同诊所的项目数差好几倍?
最常见的原因是处方时长不同。有研究用 12 个月数据算过,28 天处方占全部片剂与胶囊的近一半。用满 28 天的诊所,同一患者一年开出的项目数约为用 56 天处方诊所的两倍。其次是人群结构与合并症负担差异。

Q4:平台被 Cloudflare 拦住怎么取数?
直接走上游。NHSBSA 开放数据平台的 CKAN 接口无需密钥,可按数据集名取资源清单,再拉按月 CSV。全量月度文件约七 GB,对象存储另有 zip 镜像,体积更小。这条路径不经过平台域名,稳定性更好。

Q5:BNF 九位码到底怎么分层?
前两位是章,第三四位是节,第五六位是段,第七到九位是化学物质。九位之后是可选的两位产品码与四位呈报形式码。以 0212000Y0 为例,02 指心血管系统,0212 指高脂血症用药,九位全码指向阿托伐他汀,补足十五位才能精确到某个规格的片剂。

Q6:为什么器具类的编码长度不一样?
器具不用药品的十五位结构。器具的化学物质码是四位(如 2002 代表绷带类),呈报形式码是十一位(如 20020200822)。EPD 把药品与器具放在同一张表里,任何按固定长度切分的代码都会在器具行上出错。

Q7:能不能用它评价某位医生?
不能。公布的最低层级是机构,不是个人。用机构层面的异常值去推断个人偏好,是把聚合误差转嫁给个人,既不合方法论也不合治理要求。真要评价个人处方,需要患者级数据与另一套治理框架。

Q8:数据里的成本字段该用哪一个?
NIC 是净原料成本,按基本药价计;ACTUAL_COST 是扣减折扣与加成后的实际支付。做药品价格分析用 NIC,做支付方成本分析用实际成本。两者都不能跨 2024 年 4 月直接连,因为那时起折扣算法变了。

Q9:为什么同一条记录里有时会出现空值?
地址字段与少数度量字段允许为空。抽样看,地址四为空的比例较高,邮编少量为空,个别行连项目数与成本都为空。做统计时应当显式过滤掉 ITEMS 为空的行,而不是用零填充。

Q10:这份数据能商用吗?
可以。OGL-UK-3.0 允许商业使用、改编与再发布,条件是标注来源与「NHSBSA Copyright」,且不得暗示官方背书。用于新闻报道前,官方建议先联系其传播团队核实数字。

Q11:想研究苏格兰或威尔士怎么办?
EPD 只覆盖英格兰开具的处方,苏格兰与威尔士有各自的处方数据发布渠道。若要做四地对比,必须分别取数,并注意各地编码与口径不完全一致,不能直接套用英格兰的 BNF 层级。

Q12:平台的异常值排名能直接当审计清单用吗?
可以作为初筛,不能作为结论。排名只回答「偏离同侪多少」,不回答「为什么偏离」。用它约谈前,至少要先排除处方时长、人群构成、机构合并这三个口径因素,§4.4 的案例就是标准的排除流程。

术语表

术语 英文 含义
项目数 ITEMS 某药品在某机构某月出现的处方条数
呈报形式 Presentation BNF 编码的最细层,含剂型与规格
化学物质 Chemical Substance BNF 编码的第九位层,跨厂家可比的药名单位
净原料成本 NIC 按基本药价计算的成本
实际成本 ACTUAL_COST 扣减折扣与加成后的实际支付额
平均日剂量 ADQ 成人常规日剂量的参照值
处方成本分析 PCA NHSBSA 按调配方汇总的成本统计
英文处方数据集 EPD NHSBSA 按处方者汇总的月度处方明细
二级保健药品数据 SCMD 医院侧药品使用数据
整合照护委员会 ICB 2022 年起英格兰的委托机构
临床委托组 CCG 2022 年前的委托机构
初级保健网络 PCN 若干诊所组成的地域协作单元
患者群体导向 PGD 药房可不经处方直接供药的协议
药品词典 dm+d 英国药品与器械的标准词典
系统化医学术语 SNOMED CT 临床术语编码体系
英国国家处方集 BNF 药品分类与编码体系
开放政府许可 OGL 英国政府数据的开放许可
幽灵患者 Ghost patients 已离开或已故但仍在名单上的人口
无假设方法 Hypothesis-free 先扫全量再挑异常,不预设议题
未承保变异 Unwarranted variation 无法用临床需要解释的地区差异
抗菌药物管理 AMS 优化抗菌药使用的系统性措施
低优先级药品 Low-priority items 指南建议不作常规处方的药品
名单人口 List size 诊所注册的患者总数
单位价格 Price per unit 按最小计量单位的成本
披露控制 Disclosure control 防止从统计表反推个体的规则
标准率 Standardised rate 按人口规模调整后的比率
数据断点 Breakpoint 口径或算法发生变更的时间点

附录 A:核心数字核对表

下表列出正文出现的所有硬数字及其来源。凡标「可」的,均可用本文附带的脚本按同一路径复算。

项 值 来源 可否自行复算
单月新增记录 约 1,700 万行 NHSBSA EPD with SNOMED 数据集说明 可(下载整月文件计数)
2026-08 文件体积 7.4 GB 数据集资源清单 size 字段 可
单月处方项目总数 103,330,941 PCA 202608 文件全量求和 可
单月净原料成本 967.3 百万英镑 PCA 202608 文件全量求和 可
PCA 单月行数 518,836 PCA 202608 文件行数 可
单月呈报形式数 20,550 PCA 202608 去重 可
单月化学物质数 1,780 PCA 202608 去重 可
BNF 码表行数 55,589 Version 90 码表 可
BNF 章数 21 Version 90 码表去重 可
BNF 化学物质码数 3,000 Version 90 码表去重 可
BNF 产品码数 35,516 Version 90 码表去重 可
抽样段行数 4,834 前 2 MB 区间下载 可
抽样段诊所数 30 同上,去重 可
抽样段项目数 35,632 同上,求和 可
抽样段成本 231,540.84 英镑 同上,求和 可
案例诊所项目数 4,856 EPD 202608 单所求和 可
案例诊所成本 35,567.22 英镑 同上 可
案例诊所行数 289 同上 可
案例首化学物质项目数 2,550 按化学物质聚合 可
案例高价器具项目数 193 同上 可
处方者名录行数 160,534 Prescriber Details 202609 可
处方者名录诊所数 11,780 同上,去重 可
处方者类型数 8 类 同上,统计 可
28 天处方占比 48.5% MacKenna 2024 预印本摘要 否(可回原文)
干预试验样本 40 个 CCG BMC HSR 2025 摘要 否(可回原文)
文献命中数 136 Europe PMC 检索 可(同一检索式)

附录 B:数字的来源分层

正文的数字不是同一个可信度。按来源分成三层,越往下越需要自己核。

层级 来源类型 典型数字 核对方式
第一层 直接从官方文件本地统计 项目总数、行数、码表规模、案例诊所数字 下载文件重跑脚本
第二层 官方元数据字段 文件体积、记录量级、许可、更新节奏 调 CKAN 接口核对
第三层 同行评议论文摘要 28 天处方占比、试验样本、文献命中 回读原文,注意版本

第一层的数字最硬,因为它们是本地算出来的,任何人跑同一段代码应当得到同一结果(除非文件被官方重新发布)。第二层次之,官方字段可能滞后于实际文件。第三层最软,因为论文摘要里的数字往往是从更大数据集里截取的,复算需要原始数据与作者代码。

一个具体提醒:本文所有「单月」数字均指 2026 年 8 月。如果目标月份不是这个月,全部数字都要重跑,不能按比例外推。处方数据有明显的季节性——呼吸系统用药在冬季上涨,过敏药在春季上涨——线性外推的误差可以到两位数。

附录 C:完整参考文献

  1. Curtis HJ, Goldacre B. OpenPrescribing: normalised data and software tool to research trends in English NHS primary care prescribing 1998–2016. BMJ Open. 2018;8(2):e019921. doi:10.1136/bmjopen-2017-019921. PMID: 29476029; PMCID: PMC5855401.
  2. Hopcroft LE, Massey J, Curtis HJ, MacKenna B, Croker R, Brown AD, 等. Data-Driven Identification of Unusual Prescribing Behavior: Analysis and Use of an Interactive Data Tool Using 6 Months of Primary Care Data From 6500 Practices in England. JMIR Med Inform. 2023;11:e44237. doi:10.2196/44237. PMID: 37074763.
  3. MacKenna B, Curtis HJ, Hopcroft LEM, Walker AJ, Croker R, Macdonald O, 等. Identifying Patterns of Clinical Interest in Clinicians’ Treatment Preferences: Hypothesis-free Data Science Approach to Prioritizing Prescribing Outliers for Clinical Review. JMIR Med Inform. 2022;10(12):e41200. doi:10.2196/41200. PMID: 36538350.
  4. Curtis HJ, MacKenna B, Reddy B, Walker AJ, Bacon S, Perera R, Goldacre B. Educational interventions delivered to prescribing advisers to influence primary care prescribing: a very low-cost pragmatic randomised trial using routine data from OpenPrescribing.net. BMC Health Serv Res. 2025;25(1):308. doi:10.1186/s12913-024-11575-y. PMID: 40001106.
  5. MacKenna B, Brown AD, Croker R, Walker AJ, Tsiachristas A, Evans D, 等. Variation in prescription duration for long term conditions: a cohort study in English NHS primary care using OpenPrescribing. medRxiv 预印本. 2024. doi:10.1101/2024.05.28.24308058.
  6. Fisher L, Wood C, Brown A, Croker R, Black S, Curtis HJ, 等. OpenPrescribing Hospitals: An open access analytics platform for hospital medicines use in England. medRxiv 预印本. 2025. doi:10.1101/2025.11.13.25340060.
  7. NHS Business Services Authority. English Prescribing Dataset (EPD) with SNOMED Code. 开放数据平台. https://opendata.nhsbsa.net/dataset/english-prescribing-dataset-epd-with-snomed-code
  8. NHS Business Services Authority. BNF Code Information — Current Year, Version 90, 2026-09. 开放数据平台.
  9. NHS Business Services Authority. Prescription Cost Analysis (PCA) Monthly Data, 2026-08. 开放数据平台.
  10. NHS Business Services Authority. Prescriber Details, 2026-09. 开放数据平台.
  11. EBM DataLab. OpenPrescribing 站点代码仓库. GitHub: ebmdatalab/openprescribing.

附录 D:任务代码

把本文所有可复算数字串成一条流水线。按顺序跑完,附录 A 里标「可」的项都能得到。

#-- 一次性取到三个关键文件:处方明细、BNF 码表、处方成本分析
python3 - <<'PY'
import json, urllib.request

def pkg(name):
    url = "https://opendata.nhsbsa.net/api/3/action/package_show?id=" + name
    with urllib.request.urlopen(url, timeout=60) as r:
        return json.loads(r.read().decode("utf-8"))["result"]

jobs = [
    ("english-prescribing-dataset-epd-with-snomed-code", "EPD_SNOMED_202608", "epd.csv"),
    ("bnf-code-information-current-year", "BNF_CODE_CURRENT_202609_VERSION_90", "bnf.csv"),
    ("prescription-cost-analysis-pca-monthly-data", "PCA_202608", "pca.csv"),
]
for name, res, out in jobs:
    d = pkg(name)
    hit = [x for x in d["resources"] if x["name"] == res][0]
    print(out, hit["url"])
PY
import csv
import collections

def audit(path, month_col="YEAR_MONTH"):
    n = 0
    prac = set()
    chem = set()
    items = 0
    cost = 0.0
    with open(path, encoding="utf-8", newline="") as f:
        for r in csv.DictReader(f):
            n += 1
            prac.add(r.get("PRACTICE_CODE"))
            chem.add(r.get("BNF_CHEMICAL_SUBSTANCE_CODE"))
            items += int(float(r.get("ITEMS") or 0))
            cost += float(r.get("ACTUAL_COST") or 0)
    return {"rows": n, "practices": len(prac), "chemicals": len(chem),
            "items": items, "cost": round(cost, 2)}

print(audit("epd.csv"))
print(audit("pca.csv"))
#-- pca 文件没有 PRACTICE_CODE,practice 数为 1(None),属预期
import csv

#-- BNF 层级去重:一次跑出六层规模,用来核对附录 A 的码表数字
sets = collections.defaultdict(set)
with open("bnf.csv", encoding="utf-8-sig", newline="") as f:
    for r in csv.DictReader(f):
        sets["chapter"].add(r["BNF_CHAPTER_CODE"])
        sets["section"].add(r["BNF_SECTION_CODE"])
        sets["paragraph"].add(r["BNF_PARAGRAPH_CODE"])
        sets["chemical"].add(r["BNF_CHEMICAL_SUBSTANCE_CODE"])
        sets["product"].add(r["BNF_PRODUCT_CODE"])
        sets["presentation"].add(r["BNF_PRESENTATION_CODE"])
print({k: len(v) for k, v in sets.items()})

附录 E:如果只记五件事

第一,它是平台不是数据集。EPD 是上游原始文件,OpenPrescribing 是把文件变成问题的那个中间层。两者许可相同,取数路径不同,混用这两个词会导致后面所有的工作都错位。

第二,它的不可替代性在「三方对比」这一个动作上。诊所、药品、月份任意两两组合都能立刻出结果,这套能力叠加在十余年的连续记录上,全球范围内没有第二个同级公开版本。

第三,它能回答的是「开了多少」,不能回答的是「为什么开、给谁开、有没有效」。没有患者、没有诊断、没有结局,这是硬边界,不是可以靠方法弥补的软缺口。

第四,跨年、跨机构、跨口径的任何比较,都要先排三个雷:处方时长、名单人口、编码与算法变更。这三个雷不排,排名就没有意义。

第五,取数的第一选择是上游 CSV 与 CKAN 接口,不是网页抓取。平台页面的访问防护会拦住程序化请求,而上游接口无需密钥、长期稳定、可复算。

编辑说明

核验时间:2026 年 10 月 26 日。数据核对方式:通过 NHSBSA 开放数据平台的 CKAN 接口取资源清单与文件,本地逐条统计;论文信息通过 Europe PMC 的检索接口取回元数据与摘要。平台站点的三个入口(主站、/api/、/data/)在本次核验时对程序化请求返回 403 与访问挑战页,因此平台侧的接口参数与页面结构依据官方代码仓库与公开论文描述,未做程序化确认;批量取数路径改走上游,相关说明已写入 §5。抽样统计基于单月文件的头部区间,行数与分布不代表全量,全量口径的数字来自 PCA 与 BNF 码表的完整文件。文中案例诊所的名称与代码为公开信息,「示例诊所名」一行仅作结构示意。所有「NHSBSA Copyright」标注要求按 OGL-UK-3.0 条款执行。


相关数据集导航

以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:

  • marketscan — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全 / 卫生服务研究
  • optum-clinformatics — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全 / 卫生服务研究
  • premier-pinc-ai — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全 / 卫生服务研究
  • openfda — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全
  • fda-sentinel — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全
  • cms-medicare-lds — 共享标签:公共卫生与流行病学 / 真实世界数据 / 卫生服务研究
  • ices-ontario — 共享标签:公共卫生与流行病学 / 药物安全 / 卫生服务研究
  • jader — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全
  • eudravigilance — 共享标签:公共卫生与流行病学 / 真实世界数据 / 药物安全
  • maude — 共享标签:真实世界数据 / 药物安全

导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

返回 AI-Ready 数据集