Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
用于测试的合成患者数据
Synthea、Persona 和模型生成数据对比,优质测试数据包含什么,以及将 Synthea 患者加载到 FHIR 服务器后发生了什么。
合成患者数据是虚构的医疗记录 — 患者、诊断、用药、实验室结果、就诊 — 生成的,使其看起来和行为都像真实的记录,这样您就可以构建、测试和演示医疗保健软件,而无需接触任何人的健康信息。 它是开发的默认选项:在测试环境中使用真实患者数据存在隐私风险,通常也是法律问题。本页将介绍获取合成数据的主要方法,每种方法的优缺点,如何围绕它设计测试,以及如何将其加载到 FHIR 服务器 — 包括我们将 Synthea 患者加载到 Anpheros 后发生的情况。
获取合成患者的三种方法
| 方法 | 示例 | 适用场景 | 注意事项 |
|---|---|---|---|
| 基于规则的模拟 | Synthea (MITRE 的开源项目): 从出生开始模拟生命历程,包含疾病模块,并导出 FHIR R4 bundles、C-CDA 和 CSV | 大批量数据、完整病史、标准格式 | 默认以美国为中心 (人口统计信息、计费资源、代码);模式的真实性取决于模块 |
| 精心设计的患者画像 | 手动设计的具有特定病症的患者 | 演示、边缘案例、可重复测试 | 患者数量少;需要有人来保持其一致性 |
| 基于真实数据的统计或机器学习生成 | 在真实数据集上训练的模型 | 研究真实性 | 如果处理不当,可能泄露真实个体信息;需要进行隐私评估,而不仅仅是“它是合成的” |
语言模型根据请求生成的文本是第四种,也是风险较高的一种来源:它读起来很流畅,但经常自相矛盾 (例如,开出没有相应病症的药物,或不可能出现的实验室数值),不应作为测试的基础。
优质测试数据应包含的内容
仅仅有逼真的平均值是不够的。代码会在边界条件下出错,因此请确保您的数据(无论是合成的还是非合成的)包含:
- 缺失和不完整的数据: 缺少参考范围的实验室结果、缺少剂量的药物、缺少出生日期的患者。
- 单位和格式: 同一项测试以 mg/dL 和 mmol/L 显示、使用逗号作为小数点、带有时区和不带时区的时间。
- 更正和历史记录: 已修改的结果、已删除的 (
entered-in-error) 条目、已解决的病症。 - 重复数据: 同一份报告发送两次。
- 长短历史记录: 新生儿、拥有十年数据的人、仅一次就诊记录的人。
- 多种语言和国家/地区: 如果您服务于多个市场。
- 同意变更: 在会话中间撤销了访问权限的应用。
将 Synthea 患者加载到 FHIR 服务器
Synthea 为每个患者生成一个 FHIR R4 transaction Bundle。我们生成了两个患者 (java -jar synthea-with-dependencies.jar -p 2 -s 4242 Massachusetts) 并将它们加载到本地的 Anpheros 实例中。第一个患者的 Bundle 包含 221 个条目:
| 保留 (Anpheros 存储的类型) | 移除 (Anpheros 不存储的类型) |
|---|---|
| Observation 61, Procedure 48, DiagnosticReport 24, Condition 15, Encounter 12, DocumentReference 12, Immunization 6, Patient, CareTeam, CarePlan, Provenance | Claim 13, ExplanationOfBenefit 13, SupplyDelivery 9, Device 2, ImagingStudy 1, MedicationRequest 1 |
加载器会询问服务器支持的类型,只保留支持的类型,并将其余的作为一次事务进行 POST:
import { readFile } from 'node:fs/promises';
import { Anpheros, apiKey } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) }); // sk_test_… key
const SUPPORTED = new Set(((await anpheros.fhir.metadata()) as any).rest[0].resource.map((r: any) => r.type));
const bundle = JSON.parse(await readFile(process.argv[2], 'utf8')); // one Synthea patient file
const kept = bundle.entry.filter((e: any) => SUPPORTED.has(e.resource.resourceType));
const out: any = await anpheros.fhir.transaction({ ...bundle, entry: kept } as any);
console.log('created', out.entry.length);
结果:在一次事务中创建了 182 个资源。保留条目之间的 urn:uuid 引用已解析为服务器 ID (例如,DiagnosticReport 的 result 指向一个存在的 Observation);指向已删除 39 个条目的引用保持不变,因此在加载之前,收集每个已删除条目的 fullUrl 并剥离或转换指向它们的保留引用,并且 Patient/{id}/$summary 生成了一个包含 15 个问题、6 个免疫接种、15 个结果和 28 个生命体征的国际患者摘要。$everything 返回了 363 个条目,包括平台添加到每次写入的 provenance。
在您依赖它之前,有三件事需要了解:
- 条件引用保持不变。 Synthea 使用条件引用指向医生、组织和地点,例如
Practitioner?identifier=http://hl7.org/fhir/sid/us-npi|9999967398。Anpheros 不会在事务中解析条件引用;它们会按原样存储,并带有其display文本,并且不会解析为资源。如果您的代码遵循这些链接,请单独加载医生和组织,并重写引用。 - 账单和供应数据已丢失。 索赔和福利说明是 Synthea 美国成本模型的核心,并且不是 Anpheros 中临床记录的一部分。
- 处方将消失,而不是被转换。
MedicationRequest被移除;如果您需要在记录中包含药物,请在加载前将其转换为MedicationStatement。
Synthea 中的名称包含数字 (Marcelo725 Gulgowski816) 是故意的,这样没有人会将其误认为是真人。
Anpheros 沙盒中的合成患者
每个 Anpheros 沙盒项目都会获得一份包含 30 名合成患者的副本,这些患者是根据精心设计的角色生成的:年龄从 3 岁到 85 岁不等,来自多个欧盟国家和语言,疾病编码为 ICD-10,用药为 ATC,实验室检查和生命体征为 LOINC,单位为 UCUM 并包含参考范围,以及六个月的历史记录和文档。一个新初始化的项目包含 30 名患者、43 种疾病、51 条用药记录、1,811 个观察值、57 份文档和 6 种过敏症。数据是确定性的——每个项目看到的都是同一个人,具有相同的值,只是 ID 不同——并且重置会恢复它。每个角色都保留一个稳定的标识符,因此 Patient?identifier=https://anpheros.com/fhir/sid/sandbox-persona|p02 始终能找到同一个人。请参阅 Free FHIR database and sandbox。
当您需要小型、连贯的记录来涵盖欧洲语言和平台自身功能时,请使用这些角色;当您需要大量数据或美式历史记录时,请加载 Synthea。
常见问题解答
什么是合成患者数据?
虚构的健康记录,在结构和模式上类似于真实记录,但并不描述任何真实的人。它允许开发人员在不使用受保护健康信息的情况下进行构建和测试。
合成数据是否默认匿名?
通过规则生成的数据(如 Synthea 的)不包含真实患者。通过在真实记录上训练的模型生成的数据仍可能泄露真实人员信息,在共享之前需要进行隐私评估。
我可以将 Synthea 数据导入 FHIR 服务器吗?
可以。Synthea 导出 FHIR R4 事务包。移除服务器不支持的资源类型,检查其如何处理条件引用,然后将每个包作为事务发布。
Anpheros 沙盒是否包含合成患者?
是的:每个项目包含 30 名患者,并有六个月的编码历史记录,外加您自己创建的最多 50 名测试患者。
相关资源
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card