信息速览
这是一套「看起来完全像真的、但每一个人都不存在」的医保理赔数据。美国联邦医疗保险与医疗补助服务中心把 2008 年 Medicare 受益人 5% 随机样本的理赔记录,用统计方法重组成约 233 万份合成档案,覆盖 2008 至 2010 三个年度,文件结构与真实理赔高度一致,变量数却少了一大截。它的用途从第一天起就被写死在官方说明里:让软件开发者、研究者和学生在拿到真实数据之前,先把程序、管线、教学案例全部跑通。
它的价值与它的风险是同一件事。因为结构同构,你写好的 SQL 和 Python 换到真实理赔上基本还能用;因为内容全合成,你在这套数据上算出来的任何比率、任何回归系数,都不对应美国真实的任何一个人。官方在 Codebook 里用了一句话把这件事说死:合成过程显著改变了变量之间的相互依赖与协变关系,用它做出的单变量统计与回归系数是有偏的。
这篇词条要解决的正是这个混淆点:什么情况下它是最省事的选择,什么情况下它会把你带进一个看起来有数字、实际上没有结论的坑。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 中文名 | CMS 合成公共使用文件(Medicare 理赔) |
| 英文名 | CMS Linkable 2008-2010 Medicare Data Entrepreneurs’ Synthetic Public Use File |
| 常用缩写 | SynPUF、DE-SynPUF、DE1.0 |
| 发布机构 | Centers for Medicare & Medicaid Services(CMS) |
| 覆盖年份 | 2008、2009、2010 三个完整年度 |
| 覆盖人群 | 2008 年 Medicare 受益人 5% 随机样本的合成替身 |
| 受益人规模 | 每年约 230 万名合成受益人 |
| 文件类型 | 受益人摘要、住院、门诊、医生/供应商、处方药事件,共五类 |
| 分发方式 | 拆成 20 个互斥样本,每样本约 0.25% |
| 链接键 | DESYNPUF_ID,16 位加密标识 |
| 编码体系 | ICD-9-CM 诊断与操作码、HCPCS、NDC-11、Revenue Center |
| 记录格式 | 逗号分隔文本(CSV),配 SAS 读入程序 |
| 许可 | 公有领域,随 CMS 公开使用数据免责条款发布 |
| 获取门槛 | 免费下载,不注册、不签协议 |
| 可否推断真实人群 | 否,官方明确说明只有非常有限的推断价值 |
§1 它要解决的具体麻烦
1.1 真实医保理赔的等待成本,逼出了一套替身文件
美国 Medicare 的理赔数据并不是拿不到,而是拿得慢、拿得贵、拿得麻烦。要分析真实受益人级别的理赔,通常得走研究数据申请流程:提交研究方案、通过隐私审查、签署数据使用协议、支付费用,再等上数月,拿到的还常常只是限制数据集而非可识别数据。对于一个只想验证「我这段 SAS 程序能不能把住院和门诊拼起来」的软件团队,这个门槛显然不合适。
SynPUF 就是冲着这段空白来的。官方把它定位成三件事:让数据创业者开发和构建最终能应用到真实 CMS 理赔数据上的软件与应用;在研究机构申请真实数据之前,先把研究者训练到熟悉 CMS 理赔数据的用法与复杂度;在不牺牲受益人隐私的前提下支持安全的探索性数据挖掘。三件事有同一个前提——数据必须长得足够像真的,否则在它上面练出来的东西毫无迁移价值。
这个定位直接决定了数据集的形态。它不是一份「简化版真实数据」,而是一份「按真实数据规格重新组装出来的假数据」:文件类型、变量名、编码体系、每行的粒度全部对齐真实理赔,只有内容被换掉了。
1.2 三条常见的错误期待
使用者第一次接触这套文件时,最容易带着以下三种期待进来,而三种期待都与官方定位冲突。
第一种期待是「这是一份大样本的真实医保数据,可以拿来做流行病学」。它确实大,也确实覆盖三年,但每一个 ID 都不对应真实的人。把它当作真实人群的代表性样本,等于把统计模型当作观测仪器。
第二种期待是「既然是合成的,那就当小型数据集用,跑点统计看看」。问题不在大小,而在合成方式:为了让任何一个人都无法被重新识别,生成过程刻意削弱了变量之间的关联。一个人有糖尿病、又同时用了某种药、又住院了——这种三元关联在真实理赔里是核心信号,在合成文件里会被打散。你跑出的相关性不能读成医学事实。
第三种期待是「这就是限制数据集的免费版,字段一样,只是少了敏感信息」。字段并不一样。官方说明写着结构与限制数据集非常相似,但变量数更少。有研究者在对比后给出的概括是:真实的 5% 样本文件在每个文件类型上有数百个变量,而 SynPUF 被压缩到几十到几十个量级。缺少的那些字段,恰恰是在真实项目里做精细分析时最先被调用的。
1.3 它能给到的与给不到的
把常见的需求逐条拆开,能直观看出这套文件的边界落在哪里。
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 验证一段 SQL 能不能把五年理赔按月汇总 | 同构的表结构与同名字段 | 够,而且是它最擅长的场景 |
| 跑通一套从原始文件到 OMOP 或 Sentinel 模型的 ETL | 完整五类文件与链接键 | 够,社区已有成熟转换工程 |
| 做课程作业,让学生练习理赔数据的清洗与合并 | 20 个可分批次的小样本 | 够,每样本单独下载不至于卡住机器 |
| 演示一次队列识别与倾向评分匹配的代码框架 | 真实的字段名与编码格式 | 够,但效果指标没有医学意义 |
| 估计美国老年人糖尿病的真实患病率 | 一个粗化的慢病标志列 | 不够,结果有偏且无法校准 |
| 比较两种治疗方式在真实人群中的费用差异 | 分箱后的支付金额 | 不够,粗化把差异抹平了 |
| 研究罕见病或罕见操作的样本量与效应 | 被 k-匿名规则压制的稀有记录 | 不够,稀有事件基本被削掉 |
| 训练一个能直接部署的疾病预测模型 | 合成病程与合成结局 | 不够,模型学到的是生成规则 |
| 做 2015 年之后的编码迁移或 ICD-10 相关研究 | 只到 2010 年的 ICD-9 编码 | 不够,时间与编码体系都不对 |
| 接入真实的 Medicare Advantage 就诊记录 | 仅按服务付费部分 | 不够,目录里没有这类文件 |
1.4 你的处境与它能帮到的事
同样是「我要用 Medicare 理赔」,处在不同阶段的团队,应该在这套文件上花的时间完全不同。
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 刚立项,要估算真实数据申请要多久、值不值 | 用三个月把分析流程跑一遍,判断团队是否具备处理理赔的能力 | 拿跑通的结果去写申请方案,说明具体需要哪几类 SAF 文件 |
| 在写一套能在多个理赔库里复用的解析器 | 提供最接近真实命名的字段与文件切分方式 | 把变量映射表固化下来,再接入 CMS 限制数据集做回归测试 |
| 做教学,班里没有数据使用协议和预算 | 免费、可分样本、无门槛,一人一个样本 | 指定一个样本编号做统一作业,避免全班下载全量 |
| 做合成数据方法学研究 | 提供一个官方背书的「合成 vs 真实」对照案例 | 论文里必须同时引用官方局限声明,不能只引用数据本身 |
| 已有真实数据,想找公开的复现示例 | 提供可公开分享的代码示例载体 | 把可公开的代码放在这套文件上跑通,结果留在真实数据里 |
| 想验证某个统计结论稳不稳 | 只能验证代码路径是否出错 | 稳健性检验必须换真实数据,这套文件给不了 |
| 给投资人演示一个理赔分析产品 | 可以公开截图、公开分享数据 | 演示屏上必须注明数据为合成,否则构成误导 |
1.5 一句话判断
SynPUF 是一套「用于把流程跑通的仿真理赔」,它的正确用途是验证程序,不是估计人群;任何以它为依据的患病率、费用或效应量结论都应当被弃用。
1.6 不适合谁:四条边界
第一条边界,不适合任何以真实人群为推断对象的研究。 这不是能力问题而是设计问题。官方说明里「非常有限的推断研究价值」这句话的落点是整个文件族,不是某个子集。用它做队列研究的基线特征表,做出来的百分比会被审稿人直接质疑。
第二条边界,不适合需要时间序列延续性的研究。 数据止于 2010 年,编码体系是 ICD-9-CM。2015 年 10 月美国切换 ICD-10-CM 之后的所有理赔,编码粒度完全不同。把 2010 年的 ICD-9 与 2016 年的 ICD-10 拼在同一条时间轴上,会制造出虚假的趋势断点。
第三条边界,不适合研究 Medicare Advantage 参保人。 这套文件只有按服务付费的理赔。而 Medicare Advantage 的参保比例在 2008 年之后持续上升,这意味着它天然只能代表「传统 Medicare」那一部分人,且这部分人的构成随时间变化。
第四条边界,不适合替代限制数据集做合规审查。 有些团队想用它预先演练合规流程,这可以,但要清楚它本身不触发任何数据使用协议:在它上面跑通的合规检查,不能证明你在真实数据上也会合规。
§2 数据构成与规格
2.1 五类文件与它们的记录粒度
SynPUF 的文件族不是一个平面表,而是五个粒度不同的文件,靠同一个受益人键串起来。理解每类文件「一行代表什么」,是接入这套数据的第一步。
| 文件类型 | 一行代表 | 三年是否合并 | 官方变量数 | 主要用途 |
|---|---|---|---|---|
| 受益人摘要(Beneficiary Summary) | 一名受益人在某一年 | 按年拆成三个文件 | 官方未公开总表,社区整理约 33 列 | 人口学、参保月份、慢病标志、年度费用 |
| 住院理赔(Inpatient Claims) | 一次住院理赔 | 三年合并为一个文件 | 76 | 住院次数、住院支付额、诊断与操作码 |
| 门诊理赔(Outpatient Claims) | 一次门诊理赔 | 三年合并为一个文件 | 142 | 门诊与急诊利用、程序码、收入中心 |
| 医生/供应商理赔(Carrier Claims) | 一次医生或供应商理赔 | 三年合并,且按体量再拆为 A、B 两个文件 | 142 | 线级别的诊疗项目、HCPCS、地方性诊断码 |
| 处方药事件(Prescription Drug Events) | 一次配药事件 | 三年合并为一个文件 | 8 | D 部分药品使用、数量、供应天数、费用 |
这里有一处容易被忽略但很关键:住院、门诊、医生三类文件虽然三年合并,但并没有单独的年字段,年份要靠服务开始日期或服务结束日期去推。官方在说明中明确建议按理赔结束日期定年,因为跨年住院(12 月入、次年 1 月出)按开始日期会被算进上一年。
2.2 字段与记录的完整字典
下面按文件类型逐列梳理,只列结构与边界,不做取值分布统计。字段名保留原样,因为跨库复用时这些名字就是迁移成本的主要来源。
受益人摘要的核心字段。
| 字段 | 含义 | 处理状态 |
|---|---|---|
| DESYNPUF_ID | 受益人加密标识,跨文件链接键 | 专为本文件生成,不携带个人信息 |
| BENE_BIRTH_DT | 出生日期 | 扰动处理,具体规则官方未逐条公开 |
| BENE_DEATH_DT | 死亡日期 | 扰动处理,多家分析指出真实死亡事件的死亡日为空白 |
| BENE_SEX_IDENT_CD | 性别代码 | 保留原始编码 |
| BENE_RACE_CD | 种族代码 | 保留原始编码 |
| BENE_ESRD_IND | 终末期肾病标志 | 保留原始编码 |
| SP_STATE_CODE | 居住州代码 | SP 前缀,粗化过的地理标识 |
| BENE_COUNTY_CD | 居住县代码 | 粗化处理 |
| BENE_HI_CVRAGE_TOT_MONS | 住院保险覆盖月数 | 保留 |
| BENE_SMI_CVRAGE_TOT_MONS | 补充医疗保险覆盖月数 | 保留 |
| BENE_HMO_CVRAGE_TOT_MONS | 管理式医疗覆盖月数 | 保留 |
| PLAN_CVRG_MOS_NUM | 计划覆盖月数 | 保留 |
| SP_ALZHDMTA / SP_CHF / SP_CHRNKIDN | 阿尔茨海默、心衰、慢性肾病标志 | SP 前缀,慢病标志 |
| SP_CNCR / SP_COPD / SP_DEPRESSN | 癌症、慢阻肺、抑郁标志 | SP 前缀,慢病标志 |
| SP_DIABETES / SP_ISCHMCHT | 糖尿病、缺血性心脏病标志 | SP 前缀,慢病标志 |
| SP_OSTEOPRS / SP_RA_OA / SP_STRKETIA | 骨质疏松、类风湿与骨关节炎、卒中与短暂脑缺血标志 | SP 前缀,慢病标志 |
| MEDREIMB_IP / BENRES_IP / PPPYMT_IP | 住院部分的医保报销、受益人自付、人均支付 | 年度汇总列,粗化 |
十一个慢病标志是这张表里最值得单独说的一列。它们的变量名与真实 Medicare 文件一致,但在真实文件里是 CMS 依据理赔推导出来的既有标志,在 SynPUF 里则是合成过程本身的产物:合成产生了理赔,理赔又推导出标志。这意味着标志与理赔记录的一致性是由生成规则保证的,而不是由医学事实保证的。
住院理赔的字段骨架。
| 字段组 | 列数 | 内容 |
|---|---|---|
| 标识 | 3 | DESYNPUF_ID、CLM_ID、SEGMENT |
| 日期 | 2 | CLM_FROM_DT、CLM_THRU_DT |
| 机构与医师 | 4 | PRVDR_NUM、AT_PHYSN_NPI、OP_PHYSN_NPI、OT_PHYSN_NPI |
| 支付 | 3 | CLM_PMT_AMT、NCH_PRMRY_PYR_CLM_PD_AMT、NCH_BENE_BLOOD_DDCTBL_LBLTY_AM |
| 诊断 | 10 | ICD9_DGNS_CD_1 至 ICD9_DGNS_CD_10 |
| 操作 | 6 | ICD9_PRCDR_CD_1 至 ICD9_PRCDR_CD_6 |
| 受益人与收入中心 | 3 + 45 | 自付额、共付额、入院诊断码,以及 HCPCS_CD_1 至 HCPCS_CD_45 |
住院文件同时带诊断码与操作码,这一点决定了它是这套数据里唯一能支撑「诊断 + 手术」联合分析的机构类文件。操作码列数只有六个,而真实住院理赔在住院端允许的诊断码位更多,这是变量削减的直接后果。
医生/供应商理赔的字段骨架。
| 字段组 | 列数 | 内容 |
|---|---|---|
| 标识与日期 | 4 | DESYNPUF_ID、CLM_ID、理赔起止日期 |
| 诊断 | 8 | ICD9_DGNS_CD_1 至 ICD9_DGNS_CD_8 |
| 医师与税号 | 26 | PRF_PHYSN_NPI_1 至 _13、TAX_NUM_1 至 _13 |
| 线级项目 | 13 | HCPCS_CD_1 至 _13 |
| 线级支付 | 52 | 支付额、自付额、第三方支付、共付额四个金额族各 13 列 |
| 线级处理 | 26 | LINE_PRCSG_IND_CD、LINE_ICD9_DGNS_CD 各 13 列 |
医生文件的线级设计是这套数据里最接近真实分析的:同一笔理赔可以带最多十三条线,每条线有自己的项目码、金额与诊断码。想做「按项目计数」或「按线分摊费用」的分析,必须按线展开,不能按理赔行直接算。而官方与社区都反复提示过一点:线级金额列在空置时会留空,不能直接当 0 参与求和。
处方药事件的八个字段。
| 字段 | 含义 | 注意点 |
|---|---|---|
| DESYNPUF_ID | 受益人标识 | 与其它文件同键 |
| PDE_ID | 配药事件标识 | 单次处方事件的唯一编号 |
| SRVC_DT | 服务日期 | 格式为八位日期,需要显式解析 |
| PROD_SRVC_ID | 产品服务标识,即 NDC-11 | 十一码,需要词表才能转药品名 |
| QTY_DSPNSD_NUM | 配药数量 | 数量口径随剂型变化 |
| DAYS_SUPLY_NUM | 供应天数 | 用于推算预期用尽日 |
| PTNT_PAY_AMT | 患者支付额 | 粗化金额 |
| TOT_RX_CST_AMT | 处方总费用 | 粗化金额 |
处方文件只有八列,却是整套数据里单表行数最多的文件之一。它没有药品名称,只有 NDC 码,想按治疗类别分析必须先接外部药品词表,这一步的成本往往被低估。
2.3 一条记录的完整解剖
下面用一段可直接读入的样例,把住院理赔的一行拆开看。样例取自官方字段顺序,数值仅用于说明列的形态。
DESYNPUF_ID,CLM_ID,SEGMENT,CLM_FROM_DT,CLM_THRU_DT,PRVDR_NUM,CLM_PMT_AMT,NCH_PRMRY_PYR_CLM_PD_AMT,AT_PHYSN_NPI,OP_PHYSN_NPI,OT_PHYSN_NPI,NCH_BENE_BLOOD_DDCTBL_LBLTY_AM,ICD9_DGNS_CD_1,ICD9_DGNS_CD_2,ICD9_DGNS_CD_3,ICD9_DGNS_CD_4,ICD9_DGNS_CD_5,ICD9_DGNS_CD_6,ICD9_DGNS_CD_7,ICD9_DGNS_CD_8,ICD9_DGNS_CD_9,ICD9_DGNS_CD_10,ICD9_PRCDR_CD_1,ICD9_PRCDR_CD_2,ICD9_PRCDR_CD_3,ICD9_PRCDR_CD_4,ICD9_PRCDR_CD_5,ICD9_PRCDR_CD_6,NCH_BENE_PTB_DDCTBL_AMT,NCH_BENE_PTB_COINSRC_AMT,ADMTNG_ICD9_DGNS_CD
00013D2EFD8E45F6,10001,1,20080102,20080101,030163,6000,0,1932729346,1932729346,1932729346,0,4280,4019,2724,25000,496,25040,,,,,8856,3893,,,,,1064,0,4280
逐列读下来的信息量是这样的:这是一笔 2008 年 1 月 2 日到 1 月 1 日结束的住院理赔,医院机构号为 030163,医保支付六千余元,无第三方支付,三名医师 NPI 相同——这在合成数据里并不罕见,因为医师 NPI 是从经验分布中抽取的。诊断列依次是心衰、高血压性心脏病伴心衰、高脂血症、2 型糖尿病、慢性气道阻塞、终末期肾病;操作列是 88.56 与 38.93。
这里有一个必须点破的细节:诊断代码 25000 是原始 ICD-9 形态的五位数字串,读入时必须按字符串处理,一旦被解析成整数,前导零会丢失,0011 会变成 11。同样的坑在 D 部分的 NDC-11 上更明显——十一码里有标注为 0002 的包装段,任何数值化处理都会毁掉它。
2.4 三年记录量的核对口径
官方在数据表里给出了每类文件每年的记录数。这些数字是「规模」类数字,值得记住量级,但不必逐条背。
| 文件类型 | 2008 | 2009 | 2010 |
|---|---|---|---|
| 受益人摘要(受益人-年) | 约 233 万 | 约 229 万 | 约 226 万 |
| 住院理赔(笔) | 约 55 万 | 约 50 万 | 约 28 万 |
| 门诊理赔(笔) | 约 567 万 | 约 652 万 | 约 363 万 |
| 医生理赔(笔) | 约 3428 万 | 约 3730 万 | 约 2328 万 |
| 处方药事件(次) | 约 3993 万 | 约 4338 万 | 约 2778 万 |
表格的最右一列在真实数据里本该被读成「就诊量下降」,这里不能。官方在这张表下加了一句注:2010 年的理赔条数偏低,来自死亡损耗与披露处理的部分影响。两层原因要分开理解——死亡损耗是自然现象,受益人陆续去世导致理赔自然减少;披露处理是构造现象,压制规则会在某些年份削掉更多记录。两者叠加,任何跨年比较都必须先控制这一点,否则会把构造假象读成医疗行为变化。
2.5 与同类理赔资源的字段差异
把这套文件与库内其它理赔类资源并排放,差异集中在四个维度。
| 维度 | CMS SynPUF | CMS 限制数据集 | MIMIC-IV | NHIS |
|---|---|---|---|---|
| 数据性质 | 全合成 | 真实受益人,去标识化 | 真实患者,去标识化 | 真实受访者自报 |
| 覆盖人群 | 2008 年 Medicare 5% 样本的替身 | Medicare 参保人 | 单家医院就诊人群 | 全国代表性家庭样本 |
| 变量数 | 压缩后的几十列 | 每类文件数百列 | 多表、按 OMOP 组织 | 问卷题项数百个 |
| 获取门槛 | 免费直接下载 | 申请、协议、付费 | 培训认证后下载 | 免费注册下载 |
| 可否推断真实人群 | 否 | 可以,受抽样框限制 | 单中心,需外推论证 | 可以,需调查加权 |
这张表最该带走的一句话是:SynPUF 与限制数据集的差别不在字段多少,而在「有没有真实的人」。前者是后者结构上的影子,影子能告诉你物体轮廓,判断不了物体的重量。
§3 它是什么:身份层
3.1 一个被写进名字的定位
英文全称里有一个词最不该被跳过:Data Entrepreneurs’。它直译是「数据创业者」,指向 CMS 当初设想的首批使用者——想基于 Medicare 理赔做产品、却拿不到真实数据的软件公司。这个定位在官方页面的用途表述里被重复了三次,且三次都是「软件与应用的开发」「研究者的训练」「安全的数据挖掘」,没有一次提到「人群估计」。
名字里的另一个词是 Linkable。它意味着跨文件追踪同一个人是被鼓励的:你可以把一个受益人三年的住院、门诊、医生、处方事件全部串起来,形成一个纵向档案。这个能力在真实公开数据里极为罕见,也正是 SynPUF 在合成数据领域被反复引用的原因。
第三个关键词是 Synthetic。官方在 Codebook 里给了它一个非常硬的定义:没有任何一名受益人是真实的 Medicare 受益人,他们都是为代表真实受益人而存在的合成受益人。这句话不是免责套话,而是整个数据集的制作目标声明——它要代表,不要复制。
3.2 五个文件不是五张表,而是一条证据链
多数人把五类文件理解成「五个独立的数据集」。更准确的理解是:它们是一条证据链的不同环节。
受益人摘要回答「这是谁、有什么病、这一年医保花了多少」;住院、门诊、医生三类理赔回答「这一年发生了什么、花在什么地方」;处方事件回答「吃了什么药、吃了多久」。四个环节都挂在 DESYNPUF_ID 上,缺任何一个环节,纵向档案就断掉一截。
这个链式结构决定了接入顺序:先把受益人摘要读进来,确定分析队列;再用队列的 ID 去过滤四类事件文件;最后按需回填事件细节。反过来做——先读事件表再找受益人——在小样本上没问题,在全量上会把内存吃光,因为事件表比受益人表大两个数量级。
3.3 二十个样本,不是一个整体
官方把每一类文件都拆成二十份发布,每份约相当于 0.25% 的样本,并保证同一个受益人的全部理赔落在同一编号的样本里。这个设计常被误读成「随机抽样」或「数据分片」,实际上它是一个可用性设计:让只需要少量数据的用户不必把全量拖下来。
拆分的代价是链接顺序被固定了。想链接受益人与其理赔,必须样本编号对齐:受益人摘要的样本 7 只能连住院、门诊、医生、处方的样本 7。跨样本链接在这个设计下是无效的,因为样本之间互斥,同一个人不会出现在两个样本里。
3.4 版本只有一代
这套文件只有 DE1.0 一个版本,此后没有更新。这与多数数据集「持续维护」的直觉相反:它不是一份需要跟踪版本号的数据资源,而是一份已经封存的样本。官方没有为它安排替代版本,也没有公布更新计划。
这一点在工程上有实际含义。如果一套管线要在未来十年里持续运行,它不能只依赖 SynPUF,因为这套数据的编码体系、覆盖年份、人群构成都在 2010 年冻结;它只能作为管线的第一道回归测试,无法承担长期演进。
§4 它的可信度从哪来:质量层
4.1 一个罕见的坦白:官方自己说它不够准
数据集文档里主动声明「推断价值有限」的并不少,但把话说得这么具体的并不多。官方 Codebook 的原话是:合成过程使用显著削弱了文件产生关于真实 Medicare 受益人人群可靠推断的分析效用,也就是说,用 SynPUF 做出的单变量统计与回归系数会有偏。
这句话有两层。第一层是「会偏」,这是所有合成数据的共性;第二层是「偏在哪」——官方点名单变量统计与回归系数,恰恰是使用者最常用的两类产物。它没有说「不要用」,而是精确标出了所有输出都需要加注的位置。
4.2 官方给出的「能用」清单
坦白之外,官方也给了一份可用的说明,这份说明比多数人以为的更细。Codebook 按分析粒度区分了合成文件的可信程度。
| 分析粒度 | 官方表述的可信程度 | 实际含义 |
|---|---|---|
| 人口学特征 | 与 2008 年全量参保人的单变量频数吻合 | 出生、死亡、性别、种族、州县的分布可以被近似还原 |
| 临床变量 | 能给出「某病大概有多少例」的区间 | 可用于资助申请时的样本量估算 |
| 多变量关联 | 未给出任何可用承诺 | 跨变量的效应量不可信 |
| 时间序列 | 未给出承诺,且 2010 年有构造性下降 | 不能做趋势分析 |
这张表把前面反复强调的边界落到操作层面:单变量的边际分布是这套文件里唯一被官方背书的部分,而所有需要「两个变量同时出现」的分析,都在承诺范围之外。这也解释了一个常见困惑——为什么有人用它重算人口年龄结构觉得挺准,一转头算合并症与费用的关系就完全不对劲。两件事的可信度本来就不在同一个层级上。
4.3 案例:一张卡片的三年档案
为了把结构讲透,这里用一名虚构受益人「卡 7 号」走一遍完整链路。这个案例在 §7 与 §9 会再次被引用。
设想你在样本 7 的受益人摘要里找到一名 1942 年出生的女性,2008 至 2010 三年都有完整的医疗保险覆盖月数,慢病标志列里糖尿病与心衰两项被置位。接下来去样本 7 的四类事件文件里按她的 ID 检索,会看到三类典型现象。
第一类是可预期的完整性:三年的住院、门诊、医生、处方事件都能找到,日期范围覆盖三年,说明这张卡片在整个观察窗内是活跃的。
第二类是需要小心处理的断点:她在 2010 年中途去世,死亡日期有值,之后的事件应当消失。这张卡片的死亡日期是扰动过的,真实文件里死亡事件对应的具体日期经常是空白,两者不能混为一谈。
第三类是合成留下的指纹:她的诊断码序列在三年里高度重复,几乎每次住院都带着同一组诊断;每次处方的供应天数集中在少数几个取值上。这不是病人的真实就诊模式,而是生成过程从有限的经验分布里抽取的结果。
§4.3 的案例说明了一件事:单独看一张卡片,它像真的;看一百张卡片的模式,它露出合成痕迹。使用者的判断能力应当建立在后一种视角上。
4.4 三处必须自己验证的地方
官方文档给出的是承诺,不给出逐项校验结果。以下三处是实际接入时最应该自己动手核对的。
第一处是死亡日期的处理。 社区分析指出,真实文件里死亡事件对应的死亡日经常空白,而 SynPUF 里死亡日期有值的记录占比明显更高。如果你的分析依赖「按死亡日期做随访截止」,必须自己确认这一点,并在论文里说明用的是哪一套口径。
第二处是金额列的缺失。 线级金额列在不适用的线上会留空,而不是填零。任何求和、求均值的操作前都要先决定:空值当零,还是当缺失丢弃。两种处理会给出完全不同的费用结论。
第三处是样本编号的对齐。 二十个样本互斥,链接时必须编号一致。这一点在文件名里能看出来,但在数据加载脚本里极容易被 glob 一次性读全再合并,合并后才发现体积暴涨。
§5 怎么把它拿到手并用起来:取数层
5.1 官方入口与层级结构
官方入口分三层:顶层的合成文件总述页,中层的 DE-SynPUF 专项页,底层的二十个样本下载页。总述页说明这个文件族「是什么、为什么做」;专项页给出五类文件的记录数表与样本编号索引;样本页给出该样本下所有压缩包的直链。
| 层级 | 页面 | 上面有什么 |
|---|---|---|
| 总述层 | 合成公共使用文件首页 | 文件族定位、后续合成 PUF 的索引 |
| 专项层 | DE-SynPUF 页面 | 五类文件三年记录数、二十个样本入口、用户手册下载 |
| 样本层 | DE1.0 Sample N 页面 | 该样本八个压缩包、配套 SAS 读入程序、Codebook |
一个实际操作建议:先读专项层的记录数表,决定要几个样本;再去样本层下载。直接冲样本层容易一次性把八类压缩包全拖下来,而如果只做受益人与处方分析,住院和医生的压缩包并不需要。
5.2 一个样本里有哪八个文件
每个样本解压后是八个 CSV,这个结构在社区工程里被反复确认。理解它的理由不是好奇,而是它决定了加载顺序与内存峰值。
#-- 以样本 1 为例,列出下载页上该样本包含的压缩包
#-- 实际文件名以官方页面为准,此处按官方命名规则给出
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_Beneficiary_Summary_File_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2009_Beneficiary_Summary_File_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2010_Beneficiary_Summary_File_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Inpatient_Claims_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Outpatient_Claims_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Carrier_Claims_Sample_1A.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Carrier_Claims_Sample_1B.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Prescription_Drug_Events_Sample_1.zip"
八个文件里,受益人摘要有三份(每年一份),其余四类各一份;医生理赔因为体量大被拆成 A、B 两份,读入后必须合并。这几个压缩包是分样本设计的直接产物,也是「先读受益人、再读事件」这一加载顺序的由来。
5.3 用 pandas 读入并保住前导零
读入阶段最常见的错误是类型推断。DESYNPUF_ID、CLM_ID、诊断码、操作码、HCPCS、NDC 全部必须按字符串读,一旦被推断成整数,前导零消失、科学计数出现,后续所有关联都会悄悄错位。
import pandas as pd
#-- 所有标识列与编码列一律按字符串读,避免前导零丢失
id_cols = ["DESYNPUF_ID", "CLM_ID", "PRVDR_NUM"]
code_prefixes = ("ICD9_", "HCPCS_", "LINE_ICD9_", "ADMTNG_")
dtype_inpatient = {c: "string" for c in id_cols}
df_ip = pd.read_csv(
"DE1_0_2008_to_2010_Inpatient_Claims_Sample_1.csv",
dtype=dtype_inpatient,
low_memory=False,
)
#-- 诊断与操作码列单独抽出,统一转字符串并保留空值语义
code_cols = [c for c in df_ip.columns if c.startswith(code_prefixes)]
for c in code_cols:
df_ip[c] = df_ip[c].astype("string").str.strip()
#-- 日期列显式解析,按理赔结束日定年
for c in ("CLM_FROM_DT", "CLM_THRU_DT"):
df_ip[c] = pd.to_datetime(df_ip[c], format="%Y%m%d", errors="coerce")
df_ip["claim_year"] = df_ip["CLM_THRU_DT"].dt.year
print("行数:", len(df_ip), "列数:", df_ip.shape[1])
print(df_ip["claim_year"].value_counts().sort_index())
最后一行输出就是官方记录数表的复核:三年的条数应当与专项页上的表一致。如果不一致,先怀疑读入时的行过滤或日期解析,而不是先怀疑数据。
5.4 把受益人、住院与处方串成纵向档案
链接三步走:取队列、过滤事件、按年聚合。下面这段代码是这套数据最典型的用法模板,换成真实理赔时只需要改文件名与字段映射。
import pandas as pd
#-- 第一步:读受益人摘要,用 2008 年这一份确定分析队列
bene = pd.read_csv(
"DE1_0_2008_Beneficiary_Summary_File_Sample_1.csv",
dtype={"DESYNPUF_ID": "string", "BENE_COUNTY_CD": "string"},
low_memory=False,
)
#-- 慢病标志在官方文件里是字符型的 0/1,需要显式转换
bene["has_diabetes"] = bene["SP_DIABETES"].astype("string").eq("1")
cohort = bene.loc[bene["has_diabetes"], ["DESYNPUF_ID", "BENE_SEX_IDENT_CD", "SP_STATE_CODE"]]
#-- 第二步:用队列 ID 过滤事件表,先过滤再合并,避免笛卡尔积
ids = set(cohort["DESYNPUF_ID"].dropna())
pde = pd.read_csv(
"DE1_0_2008_to_2010_Prescription_Drug_Events_Sample_1.csv",
dtype={"DESYNPUF_ID": "string", "PDE_ID": "string", "PROD_SRVC_ID": "string"},
low_memory=False,
)
pde = pde[pde["DESYNPUF_ID"].isin(ids)]
pde["SRVC_DT"] = pd.to_datetime(pde["SRVC_DT"], format="%Y%m%d", errors="coerce")
pde["supply_days"] = pd.to_numeric(pde["DAYS_SUPLY_NUM"], errors="coerce")
#-- 第三步:按受益人-年汇总处方事件数与供应天数
pde["year"] = pde["SRVC_DT"].dt.year
profile = (
pde.groupby(["DESYNPUF_ID", "year"])
.agg(n_fills=("PDE_ID", "nunique"), total_supply=("supply_days", "sum"))
.reset_index()
)
print(profile.head(5))
print("队列人数:", len(ids), "有处方记录的人:", profile["DESYNPUF_ID"].nunique())
这段代码跑通不代表结论可用。total_supply 这一列在这套数据上有结构意义(用来验证同一个人一年内是否连续用药),但没有医学意义(不能读成真实糖尿病人的用药依从性)。
5.5 用 DuckDB 直接在外层做 join
样本量不大的时候,DuckDB 比 pandas 省事,尤其是多个 CSV 直接 join 的场景,它不需要把中间表全部物化到内存。
-- 先把八个 CSV 注册成视图,DuckDB 会按需读取
CREATE VIEW bene_2008 AS
SELECT * FROM read_csv('DE1_0_2008_Beneficiary_Summary_File_Sample_1.csv',
types = {'DESYNPUF_ID': 'VARCHAR', 'BENE_COUNTY_CD': 'VARCHAR'});
CREATE VIEW ip_0810 AS
SELECT * FROM read_csv('DE1_0_2008_to_2010_Inpatient_Claims_Sample_1.csv',
types = {'DESYNPUF_ID': 'VARCHAR', 'CLM_ID': 'VARCHAR'});
---- 按理赔结束日定年,统计每名受益人的年住院次数
CREATE VIEW ip_year AS
SELECT DESYNPUF_ID,
SUBSTR(CAST(CLM_THRU_DT AS VARCHAR), 1, 4) AS claim_year,
COUNT(DISTINCT CLM_ID) AS n_ip
FROM ip_0810
WHERE CLM_THRU_DT IS NOT NULL
GROUP BY ALL;
SELECT claim_year, COUNT(*) AS bene_years, SUM(n_ip) AS total_claims
FROM ip_year
GROUP BY claim_year
ORDER BY claim_year;
这段查询的输出应当能对上官方记录数表里住院那一行。对不上时,先检查 CLM_THRU_DT 是否被读成了整数,整数化会让 SUBSTR 的结果整体偏位。
5.6 换个模型再跑:OMOP 与 Sentinel 两条现成通道
SynPUF 之所以在方法学研究里被频繁当作对照组,一个重要原因是它已经被转成了主流通用数据模型,而且转换产物是公开的。
| 通道 | 维护方 | 形态 | 规模选项 | 适用场景 |
|---|---|---|---|---|
| OMOP CDM | 社区协作,托管于云对象存储 | 按 OMOP 表结构组织的关系库镜像 | 提供小、中、全量三档 | 方法学对照、工具兼容性测试 |
| Sentinel 通用数据模型 | Sentinel 项目方 | 按 SCDM 组织,含例行查询工具示例包 | 二十个互斥数据集 | 药品安全监测流程的演练 |
两条通道的意义不同。OMOP 通道适合验证「我的 OMOP 查询在另一份数据上会不会报错」;Sentinel 通道适合验证「药品安全监测的标准查询流程能不能在本数据上完成一轮」。两者都不是为了得出医学结论,而是为了让工具链在受控条件下先跑一轮。
用云对象存储直读时要注意一点:公开镜像通常允许匿名访问,但桶所在区域与请求区域不一致会产生极慢的跨区读取。把区域设成镜像所在地,速度会差一个数量级。
#-- 匿名访问公开镜像:列出全量档的顶层前缀,确认目录结构
aws s3 ls --no-sign-request --region us-east-1 s3://synpuf-omop/
#-- 只拉一份小规模档做工具兼容性测试,不下全量
aws s3 cp --no-sign-request --region us-east-1 \
s3://synpuf-omop/1k/ ./synpuf-1k/ --recursive
§6 与库内条目的关系
6.1 关系图谱
库内与这套文件最接近的有五条,它们的差别恰好能把这个数据集的位置标出来。
| 库内档案 | 关系 | 关键差异 |
|---|---|---|
| CMS DE-SynPUF | 同一数据集族的专门档案 | 该档案按 OMOP 转换与工程坑点组织,本篇按「合成与真实的边界」组织;两者字段口径一致,可互为补充 |
| CMS Medicare LDS | 原型与真身 | LDS 是真实受益人经去标识化后的限制数据集,需申请与付费;SynPUF 是它的结构影子 |
| SEER-Medicare | 想做的分析 vs 该用的数据 | 若目标是癌症与理赔的个体级链接研究,SEER-Medicare 才是正解,SynPUF 只能用来先把代码写出来 |
| MIMIC-IV | 同为理赔形状的真实数据 | MIMIC-IV 是单家医院的真实就诊记录,颗粒度到检验与生命体征;SynPUF 只有理赔汇总,但覆盖全国参保人群的替身 |
| NHIS | 人群层面而非理赔层面 | NHIS 是自报问卷,能回答「多少人说自己有病」,回答不了「这些人花了多少医保钱」 |
| eICU-CRD | 完全不同的层 | 重症监护的生理与治疗数据,与理赔无关;唯一的共同点是都需要先验证管线 |
这张表里最值得展开的是第一行。「CMS DE-SynPUF」档案与本篇描述的是同一批文件,两篇的存在不是重复,而是两种读法:前者把重心放在「怎么把它转成 OMOP、工程上有哪些坑」,本篇的重心放在「它为什么不能用来估计人群、在什么条件下可以被信任」。如果只读一篇,容易在读另一篇时产生期待落差——有人读完工程向的档案,会以为数据可以直接用于建模;有人读完本篇,会以为它毫无用处。两篇合起来才是完整图景。
6.2 检索路径
按使用目的找档案,比按名字找更快。
| 你想做的事 | 应当先看 | 再看 |
|---|---|---|
| 先把理赔管线跑通,不涉及真实患者 | 本篇 §5 与 §9 | CMS DE-SynPUF 的工程坑点 |
| 要做真实的 Medicare 理赔研究 | CMS Medicare LDS | 本篇 §7 的边界说明 |
| 做癌症与理赔的链接 | SEER-Medicare | 本篇 §6.1 的关系表 |
| 做院内重症的表型建模 | MIMIC-IV 或 eICU-CRD | 本篇只作方法参考 |
| 做人群健康行为的问卷分析 | NHIS | 本篇不适用 |
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
这一节最容易被误判的地方,是把「合成数据」当成「质量较差的数据」。两者不是一回事。一份质量较差的真实数据,问题在噪声、缺失、录入错误;SynPUF 的问题不在这里——它的字段完整、格式规整、编码合规,甚至在很多工程指标上比真实理赔更干净。它的限制来自一个更根本的位置:它没有测量任何真实存在的东西。因此下面所有评分都应当读成「作为开发与培训载体」的评分,而不是「作为真实人群证据」的评分。前者它表现不错,后者它从设计上就被排除在外。
7.1 五维评分
评分参照数据质量框架的常用维度(完整性、准确性、一致性、时效性、可得性),另加一项针对合成数据的专项维度。
| 维度 | 评分 | 依据 |
|---|---|---|
| 结构完整性 | 5/5 | 五类文件齐全,跨文件链接键统一,三年连续 |
| 字段一致性 | 4/5 | 变量名与真实 CMS 文件一致,被粗化的变量加 SP 前缀,可追溯 |
| 编码规范性 | 4/5 | ICD-9、HCPCS、NDC-11 编码体系规范,但停留在 2010 年的版本 |
| 时效性 | 1/5 | 数据止于 2010 年,此后无更新,编码体系已过时 |
| 可得性 | 5/5 | 免费直下,无需注册,二十个样本可分批取得 |
| 合成透明度 | 5/5 | 官方明确声明合成性质、明示推断价值有限、公开生成思路 |
| 推断可用性 | 1/5 | 多变量关系被破坏,单变量统计有偏,官方不建议用于人群推断 |
这七项加在一起给出的结论很清晰:工程侧的几项接近满分,推断侧的两项接近零分。选择它之前,先确认自己需要的是前者还是后者。
下表把评分换成一句话的问题形式,方便对照自己的用途。
| 你的用途 | 对应的评分项 | 是否过线 |
|---|---|---|
| 写解析器、跑 ETL、验证字段映射 | 结构完整性、字段一致性 | 过线 |
| 做课程演示、公开分享截图 | 可得性、合成透明度 | 过线 |
| 训练研究者熟悉 CMS 理赔 | 结构完整性、字段一致性 | 过线 |
| 估算队列规模以写资助申请 | 结构完整性、边缘分布 | 勉强过线 |
| 估计患病率、费用均值、效应量 | 推断可用性 | 不过线 |
| 做近年趋势或 ICD-10 研究 | 时效性 | 不过线 |
| 做罕见病、罕见操作 | 推断可用性、稀有事件抑制 | 不过线 |
7.1b DAIMS 质量六维打分
上面是通用质量维度的读法。若按 DAIMS 框架的六个维度重新走一遍,落点会略有不同,但结论一致:这套文件的强项全部集中在「结构与文档」一侧,弱项全部集中在「内容真实性」一侧。
| DAIMS 维度 | 本数据集的状况 | 分数 |
|---|---|---|
| 数据来源与谱系 | 种子来自 2008 年 5% 真实样本,合成链条在文档中有说明 | 4/5 |
| 数据建模与结构 | 五类文件、统一链接键、跨年一致,可直接映射到通用数据模型 | 5/5 |
| 数据定义与元数据 | Codebook 逐字段给出名称与含义,被粗化变量有 SP 前缀标记 | 5/5 |
| 数据质量与内容真实性 | 边际分布近似真实,但协变被改变,内容不对应任何真实个体 | 2/5 |
| 数据保护与访问控制 | 全合成、无真实个人信息、公开下载,重识别风险极低 | 5/5 |
| 使用与许可透明度 | 明确声明推断价值有限、明确许可性质、明确禁止的用法 | 5/5 |
在这六维里,「数据保护」与「内容真实性」是一对反向指标:数据保护做得越好,内容真实性就被牺牲得越多。这不是执行失误,而是合成数据的必然权衡。DAIMS 把两者分开列,恰好让这个权衡可见——使用者看到保护项满分时,应当立刻想到真实性那一项不会也满分。
7.2 合成方法的可追溯性
官方公开了生成思路,但没有公开完整算法参数。可追溯的部分包括:源数据是 2008 年 Medicare 受益人 5% 随机样本;合成采用种子-捐赠者式的热卡法,每个合成受益人的理赔集来自多个捐赠者;披露限制手段包括变量削减、稀有记录抑制、日期扰动与连续变量粗化;变量名保留原名,被显著粗化的加 SP 前缀。
不可追溯的部分包括:具体扰动参数、抑制阈值、捐赠者数量的分布、各年份差异化的处理规则。这决定了使用者无法复现一份「同样的合成数据」,只能在官方发布的那一份上工作。
7.3 已知的、可枚举的偏差
偏差之所以要枚举,是因为它们决定了什么样的分析会出错、错在哪个方向。
| 偏差 | 来源 | 受影响的分析 | 应对 |
|---|---|---|---|
| 变量间关联被削弱 | 为保证不可重识别而人为打散协变 | 合并症与费用的关系、疗效与预后的关联 | 不用于估计效应量,只用于验证代码 |
| 稀有事件被抑制 | k-匿名规则剔除稀有组合 | 罕见病、罕见操作、小地理单元 | 换用真实数据或放大样本后重做 |
| 年份覆盖截断 | 只到 2010 年 | 趋势分析、编码迁移研究 | 不作为时间序列的组成部分 |
| 参保结构偏差 | 只含按服务付费 | 任何涉及管理式医疗的比较 | 分析前明确排除 MA 参保人 |
| 入组人群固化 | 以 2008 年样本为种子 | 新入组群体的特征研究 | 不把结论外推到 2008 年之后入组的人 |
| 死亡日期处理差异 | 扰动与真实文件的处理规则不同 | 生存分析、随访截止 | 自建口径并明确披露 |
| 2010 年记录量构造性下降 | 死亡损耗叠加披露处理 | 任何逐年对比 | 按官方注释解释,不读成行为变化 |
| 金额粗化 | 连续变量分箱 | 费用均值的估计 | 只做流程验证,不做费用推断 |
7.4 外部验证矩阵
| 验证来源 | 类型 | 能支持什么 | 不能支持什么 |
|---|---|---|---|
| CMS 官方 Codebook 与用户手册 | 一手文档 | 文件结构、变量定义、合成性质声明 | 具体扰动参数 |
| CMS 官方专项页记录数表 | 一手数据 | 每类文件每年的规模 | 分布类统计 |
| Sentinel 项目的 SCDM 转换包 | 第三方工程 | 转成通用模型后工具链可用 | 医学结论 |
| 社区 OMOP 镜像 | 第三方工程 | 跨模型工具兼容性 | 数据内容真实性 |
| PLOS Digital Health 合成数据综述 | 同行评议综述 | 把它列为合成数据代表性案例 | 它的具体质量评价 |
| 库内 CMS DE-SynPUF 档案 | 同源档案 | 工程坑点与字段细节 | 本篇独立的边界判断 |
这张表说明一件事:关于这套文件的外部文献几乎全部集中在「怎么用它」,而极少有文献讨论「它准不准」——因为它准不准不是一个开放问题,官方已经给了答案。
7.5 它为何能持续:作为付费数据之前的必经台阶
这套文件从 2011 年前后首次发布起就没有更新,却一直在被使用,原因不在数据本身,而在它占据的位置:它是「想用 Medicare 理赔但还拿不到真实数据」这段等待期里唯一的公开替身。只要真实数据的申请流程仍然需要数月、仍然需要付费与协议,这段等待期就会一直存在,替身就一直有用。同理,只要数据创业者和研究者需要在不接触真实受益人信息的前提下练手,它的存在就有意义。它的可持续性来自流程缺口,而不是数据质量。
§8 生态位与历史
8.1 从单项开放到可链接
这套文件不是一次成型的。它最初以单年、单文件的形式出现,后来扩展成覆盖三年的可链接版本,把「拆分发布的若干文件」变成「可以追踪同一个人的纵向档案」。这个转变是它进入方法学研究视野的分水岭:单年文件只能做横截面的练习,可链接版本才能支撑队列式分析的教学。
可链接版本的代价是合成复杂度上升。为了让同一个合成受益人在三年里保持合理的一致性(年龄递增、死亡后无记录),生成过程必须跨年协调,这也正是变量间关联被进一步打散的原因之一。
8.2 在合成数据谱系里的位置
合成医疗数据大致可分三档:完全手工构造的假数据、基于真实数据统计模型生成的仿真数据、用生成式模型学出来的数据。SynPUF 属于第二档,而且是这一档里最早、最权威的公开样本之一。
| 档位 | 代表 | 与真实数据的距离 | 主要用途 |
|---|---|---|---|
| 手工构造 | 教学用小型虚构数据 | 最远,只保证字段齐全 | 入门教学 |
| 统计模型生成 | CMS SynPUF | 中等,边际分布近似真实 | 管线开发、研究者培训 |
| 生成式模型合成 | 各类近年的扩散或生成对抗模型产物 | 较近但难以审计 | 隐私保护下的共享 |
| 真实去标识化 | CMS 限制数据集 | 最近 | 真实研究 |
这个谱系把 SynPUF 的位置说清楚了:它比手工假数据真,比生成式模型的产物可审计,但比真实去标识化数据远。选择哪一档,取决于你要解决的问题是「把程序写出来」还是「把结论写出来」。
8.3 被谁用、用在哪些环节
从公开文献与工程实践看,它的使用集中在四个环节。
第一是软件与工具的前期验证。做理赔分析工具的厂商与开源项目,普遍先在它上面跑通读入、清洗、合并、聚合的完整链路,再去接真实数据付费测试。
第二是研究者培训。官方明确把它列为培训载体,目的是让研究者在申请真实数据之前就熟悉 CMS 理赔的复杂度——变量命名、文件拆分、编码体系、跨年链接,这些「复杂度」在课堂上用真实数据讲不起。
第三是国际通用数据模型的兼容性测试。把它转成 OMOP 或 Sentinel 模型后,可以在公开条件下验证一套查询工具;这一点在药品安全监测、医疗经济学等领域尤其常见。
第四是合成数据方法学的对照实验。研究「合成数据能替代真实数据到什么程度」的团队,需要一个官方背书的合成样本作为基准。
这四个环节有一个共同点:都不需要声明「这是关于真实人群的结论」。
8.4 与「真身」并排看
把它与 CMS 限制数据集并排,能看出这对原型与真身的分工有多清楚。
| 对比项 | SynPUF | 限制数据集 |
|---|---|---|
| 记录里的人 | 合成 | 真实,已去标识化 |
| 文件类型数 | 五类 | 更多,含机构与药品等多类文件 |
| 变量数 | 每类几十列 | 每类数百列 |
| 覆盖人群 | 2008 年 5% 样本的替身 | 全部或按比例抽样的真实参保人 |
| 获取周期 | 即刻 | 数月 |
| 费用 | 零 | 按文件与用途计费 |
| 主要用途 | 程序开发、培训 | 真实研究 |
| 能否推断人群 | 不能 | 能,受抽样框与去标识化限制 |
结论不是「它不如真身」,而是「它不打算成为真身」。官方的设计目标写得很清楚:让在它上面写好的程序能够运行在限制数据集上;这个目标达到就够了,它从来不承诺替代。
§9 使用指引
9.1 三种角色的路径
软件开发者。 从样本 1 起步,只读受益人、住院、处方三个文件,先把「读入 → 清洗 → 链接 → 聚合」跑通,再扩展到门诊与医生。变量映射表要从第一天就写死,因为真实数据里的字段名偶尔会多出后缀或换用 SAS 风格,早建映射早发现。
研究者。 不要拿它做预实验的结论,拿它做两件事:一是练习队列构建与变量派生的代码,二是估算真实数据申请时需要的文件范围。在申请材料里引用它来说明「我们已在同构数据上验证了分析流程」,是一个具体且可信的表述。
教学人员。 一个样本就是一个班。让学生各自下载不同编号的样本,再做结果比对,能很自然地引出「合成数据的分布随样本波动、不能合并推断」这一课。
9.2 一条最短的可用流程
从零到跑通,最短路径是六步。这套流程经过压缩,去掉了所有与「验证结构」无关的步骤。
#-- 第一步:建目录,按样本编号分离,避免不同样本的文件混在一起
mkdir -p synpuf/sample_01 && cd synpuf/sample_01
#-- 第二步:只下本次需要的三类文件,先不碰门诊与医生
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_Beneficiary_Summary_File_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Inpatient_Claims_Sample_1.zip"
curl -sL -O "https://downloads.cms.gov/files/DE1_0_2008_to_2010_Prescription_Drug_Events_Sample_1.zip"
#-- 第三步:解压并清点文件数,应为 5 个 CSV(3 受益人年 + 住院 + 处方)
for z in *.zip; do unzip -o -q "$z"; done
ls -1 *.csv | wc -l
随后在 Python 里做两件事:读入时把标识列与编码列定为字符串;按理赔结束日定年并核对条数。核对通过后,再写真正的分析逻辑。
import pandas as pd
#-- 读入并立即核对:三年受益人-年记录数应当与官方表同量级
bene_files = {
2008: "DE1_0_2008_Beneficiary_Summary_File_Sample_1.csv",
2009: "DE1_0_2009_Beneficiary_Summary_File_Sample_1.csv",
2010: "DE1_0_2010_Beneficiary_Summary_File_Sample_1.csv",
}
counts = {}
for year, path in bene_files.items():
df = pd.read_csv(path, dtype={"DESYNPUF_ID": "string"}, low_memory=False)
counts[year] = df["DESYNPUF_ID"].nunique()
#-- 样本 1 只占全量的约 1/20,这里只做量级对照,不做精确核对
print(counts)
assert all(v > 100000 for v in counts.values()), "某个年份的读入明显异常"
如果某个年份读入后不足十万,先检查文件是否下全、解压是否报错,再检查 DESYNPUF_ID 是否被读成了数值。
9.3 引用方式
这套文件没有官方 DOI,也没有正式的方法学论文。规范做法是引用官方文档,并在正文里同时说明其合成性质。
Centers for Medicare & Medicaid Services. CMS Linkable 2008-2010 Medicare
Data Entrepreneurs' Synthetic Public Use File (DE-SynPUF). 2013.
https://www.cms.gov/data-research/statistics-trends-and-reports/medicare-claims-synthetic-public-use-files
Centers for Medicare & Medicaid Services. DE-SynPUF Data Users Guide (DE1.0).
https://www.cms.gov/research-statistics-data-and-systems/downloadable-public-use-files/synpufs/downloads/synpuf_dug.pdf
正文里建议加一句固定表述:本研究使用 CMS 发布的合成理赔文件验证分析流程,该文件不含任何真实受益人,结果不用于对真实 Medicare 人群的推断。这句话能挡掉绝大多数审稿质疑。
§10 AI 使用声明
| 项目 | 说明 |
|---|---|
| 生成方式 | 写成阶段使用大语言模型辅助整理结构与润色,全部事实以官方文档为准 |
| AI 参与范围 | 资料归纳、章节组织、代码模板编写、语言统一 |
| AI 未参与部分 | 硬数字的最终核对、边界判断、发布决策 |
| 依据来源 | CMS 官方总述页、DE-SynPUF 专项页、Codebook、数据使用者手册片段,以及一篇同行评议综述 |
| 数字口径 | 只收规模、结构、边界三类,未做任何分布统计 |
| 未核实项 | 合成过程的具体扰动参数、各年份差异化处理规则官方未公开 |
| 更新承诺 | 该数据集已封存,无更新;本篇随官方页面变动修订 |
| 使用限制 | 本篇不构成任何关于真实 Medicare 人群的医学结论 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 这是免费版的 Medicare 限制数据集 | 它是结构相似的合成替身,变量数少得多,内容全合成 | 官方 Codebook 的开篇说明 |
| 两百多万人,做流行病学够了 | 人数够,但每一个人都不对应真实个体 | 官方 Codebook 对合成受益人的定义 |
| 合成只是在真实数据上加噪声 | 变量削减、稀有记录抑制、日期扰动、金额粗化叠加,关联被刻意打散 | 官方手册的披露限制章节 |
| 2010 年数据变少说明就诊减少 | 官方注明了死亡损耗与披露处理的影响 | 专项页记录数表下的注释 |
| 变量名一样,所以行为一样 | 变量名一样是设计目标,但缺少的字段在真实数据里有 | 官方对变量数削减的说明 |
| 先在这上面跑出结论,再换真实数据验证 | 结论本身有偏,验证会变成「把偏的结论固化」 | 官方对回归系数有偏的声明 |
| 二十个样本可以合并成一个大数据集 | 样本互斥,是为了分批下载而拆的,可合并但需编号对齐 | 官方对样本设计的说明 |
| 死亡日期能直接拿来做生存分析 | 扰动口径与真实文件不同,真实文件死亡事件常留空 | 社区对两边死亡日处理的对比 |
| 金额列为空就是零 | 线级金额在不适用的线上留空,当零会低估费用 | 线级字段的空值语义 |
| 它是方法学论文的正式数据集 | 没有 DOI,也无配套的方法学论文 | 官方页面与文献检索结果 |
FAQ
Q1:SynPUF 里的受益人都是真实存在的人吗?
不是。官方 Codebook 明确写着没有任何一名受益人对应真实的 Medicare 参保人,每个 ID 都是为这套文件新生成的。DESYNPUF_ID 只用于链接,不含任何个人信息。
Q2:能不能用 SynPUF 算某个病的真实发生率和费用?
不能。官方说明明确写着合成过程改变了变量之间的依赖与协变关系,用它算出的单变量统计量与回归系数都是有偏的。它只适合验证流程能不能跑通,不适合产出关于真实人群的结论。
Q3:为什么 2010 年的理赔条数比 2008 年少?
官方在数据表下方注明,2010 年条数偏低来自死亡损耗与披露处理的部分影响。这是数据集构造层面的现象,不代表那一年美国人看病变少了。
Q4:在 SynPUF 上写好的程序,能不能直接跑真实理赔?
在变量名与文件结构层面基本可以。官方设计目标就是让在 SynPUF 上写好的程序与流程可以运行在 CMS 限制数据集上。但变量数少得多,真实数据里存在的字段在 SynPUF 中可能没有。
Q5:下载要注册或签署协议吗?
不需要。它以免费下载形式发布,登录门户即可拿到分样本压缩包。使用仍受 CMS 公开使用数据免责条款约束。
Q6:它和 CMS 限制数据集是同一份数据吗?
不是。限制数据集是真实受益人经去标识化后的理赔,需要申请与协议;SynPUF 是模拟出来的同构文件,结构与变量命名相似但内容完全合成。
Q7:二十个样本里,一个人的理赔会不会分散在不同样本?
不会。官方保证同一个受益人的全部理赔落在同一编号的样本里。这也正是跨样本链接无效的原因。
Q8:能不能把三年拼成一条时间序列做趋势分析?
不建议。年份止于 2010,且 2010 年有构造性下降,两个因素都会制造假趋势。真要做趋势,必须换用覆盖更长时间的理赔数据。
Q9:慢病标志列(SP 开头)能直接当作诊断结果用吗?
可以作为「这名合成受益人有该病的标志」使用,但要记住它由合成过程推导而来,与理赔记录的一致性由生成规则保证,而不是由医学事实保证。
Q10:数据里的药品为什么只有编码没有名字?
处方文件只保留 NDC-11 编码。要按药品或治疗类别分析,必须先接外部药品词表,把编码映射到名称与类别,这一步的成本常被低估。
Q11:这套数据以后会不会更新到 ICD-10?
官方没有更新计划,版本停留在发布时的 DE1.0。要做 ICD-10 之后的研究,只能换数据源。
Q12:我用它做课程作业,需要在作业里声明什么?
至少声明两点:数据为 CMS 发布的合成理赔文件,不含真实受益人;作业中的统计结果仅用于演示流程,不构成关于真实人群的结论。
术语表
| 术语 | 含义 |
|---|---|
| SynPUF | Synthetic Public Use File,合成公共使用文件的缩写 |
| DE-SynPUF | Data Entrepreneurs’ SynPUF,面向数据创业者的可链接合成文件 |
| 公共使用文件(PUF) | 官方直接对公众发布、无需申请的数据文件 |
| 限制数据集(LDS) | 真实受益人经去标识化、需申请与协议的限制访问数据 |
| 受益人摘要 | 以受益人-年为一行的人口学与费用汇总文件 |
| 住院理赔 | 以单次住院为一行,含诊断与操作码 |
| 门诊理赔 | 以单次门诊为一行,含收入中心与项目码 |
| 医生/供应商理赔 | 以单次诊疗理赔为一行,在线级别带项目与金额 |
| 处方药事件(PDE) | 以单次配药为一行,含 NDC 与供应天数 |
| DESYNPUF_ID | 为这套文件专门生成的受益人加密链接键 |
| CLM_ID | 理赔标识,同一理赔的多个分段共享 |
| 种子-捐赠者热卡法 | 以真实样本为种子、从多个捐赠者拼装记录的合成方法 |
| k-匿名抑制 | 出现频次低于阈值的记录被剔除的技术 |
| 粗化 | 把连续变量或精细类别合并为粗类别的处理 |
| 日期扰动 | 对日期加噪或移位,削弱重识别风险的办法 |
| ICD-9-CM | 第九版国际疾病分类临床修订版,诊断与操作编码体系 |
| HCPCS | 医疗服务供给通用编码系统,用于项目与耗材编码 |
| NDC-11 | 十一码的国家药品编码,标识具体包装 |
| 收入中心 | 机构理赔里标识费用归属科室与项目的编码 |
| 线级别 | 一笔理赔内按项目拆分的明细层 |
| 按服务付费 | 传统 Medicare 的支付方式,本数据只覆盖这类理赔 |
| 管理式医疗 | 由商业计划承保的 Medicare Advantage,本数据不覆盖 |
| 慢病标志 | 以 SP 开头的十一个慢病指示变量 |
| OMOP CDM | 观察性医疗结果合作组织的通用数据模型 |
| SCDM | Sentinel 项目的通用数据模型 |
| 死亡损耗 | 受益人去世导致后续年份记录自然减少 |
| 披露处理 | 为降低重识别风险而对数据施加的一系列处理 |
附录 A:核心数字核对表
| 项目 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 覆盖年份 | 2008–2010 | 官方专项页 | 一手 |
| 种子样本 | 2008 年受益人 5% 随机样本 | 官方 Codebook | 一手 |
| 2008 年受益人-年数 | 2,326,856 | 官方专项页记录数表 | 一手 |
| 2009 年受益人-年数 | 2,291,320 | 官方专项页记录数表 | 一手 |
| 2010 年受益人-年数 | 2,255,098 | 官方专项页记录数表 | 一手 |
| 住院理赔三年合计 | 约 133 万笔 | 官方表三列相加 | 一手推算 |
| 门诊理赔三年合计 | 约 1583 万笔 | 官方表三列相加 | 一手推算 |
| 医生理赔三年合计 | 约 9486 万笔 | 官方表三列相加 | 一手推算 |
| 处方事件三年合计 | 约 11108 万次 | 官方表三列相加 | 一手推算 |
| 文件类型数 | 5 | 官方专项页 | 一手 |
| 样本拆分数 | 20 | 官方专项页 | 一手 |
| 每样本占比 | 约 0.25% | 官方专项页 | 一手 |
| 住院文件变量数 | 76 | 官方手册片段 | 一手 |
| 医生文件变量数 | 142 | 官方手册片段 | 一手 |
| 处方文件变量数 | 8 | 官方手册片段 | 一手 |
| 链接键 | DESYNPUF_ID | 官方 Codebook | 一手 |
| 获取方式 | 免费下载,无需协议 | 官方总述页 | 一手 |
| 有无 DOI | 无 | 官方页面未提供 | 未核实反向 |
附录 B:数字的来源分层
第一层,官方页面与官方文档。 包括合成文件总述页、DE-SynPUF 专项页、Codebook 与用户手册。本词条的年份、受益人年度计数、五类文件记录数、文件数、样本拆分方式、变量数与合成性质声明全部来自这一层。这一层可以逐字引用。
第二层,第三方工程与同行评议综述。 包括 OMOP 与 Sentinel 的转换镜像,以及 2023 年发表于 PLOS Digital Health 的合成数据综述。这一层用来确认「这套文件在方法学界被如何使用」,不用于确认数据本身的统计性质。
第三层,未核实项。 包括合成过程的具体扰动参数、稀有记录的抑制阈值、各年份差异化的处理规则、20 个样本各自的精确人数。这些数字官方未逐条公开,本词条不作估计。凡是涉及这类数字的地方,一律写「官方未公开」。
附录 C:完整参考文献
- Centers for Medicare & Medicaid Services. Medicare Claims Synthetic Public Use Files. https://www.cms.gov/data-research/statistics-trends-and-reports/medicare-claims-synthetic-public-use-files
- Centers for Medicare & Medicaid Services. CMS 2008-2010 Data Entrepreneurs’ Synthetic Public Use File (DE-SynPUF). https://www.cms.gov/Research-Statistics-Data-and-Systems/Downloadable-Public-Use-Files/SynPUFs/DE_Syn_PUF
- Centers for Medicare & Medicaid Services. DE-1.0 Codebook. https://www.cms.gov/files/document/de-10-codebook.pdf-0
- Centers for Medicare & Medicaid Services. DE-SynPUF Data Users Guide. https://www.cms.gov/research-statistics-data-and-systems/downloadable-public-use-files/synpufs/downloads/synpuf_dug.pdf
- Centers for Medicare & Medicaid Services. DE1.0 Sample 1 下载页. https://www.cms.gov/data-research/statistics-trends-and-reports/medicare-claims-synthetic-public-use-files/cms-2008-2010-data-entrepreneurs-synthetic-public-use-file-de-synpuf/de10-sample-1
- Gonzales A, Guruswamy G, Smith SR. Synthetic data in health care: A narrative review. PLOS Digital Health, 2023. doi:10.1371/journal.pdig.0000082
- Sentinel Initiative. Medicare Claims Synthetic Public Use Files in Sentinel Common Data Model Format. https://sentinelinitiative.org/methods-data-tools/software-packages-toolkits/medicare-claims-synthetic-public-use-files-sentinel
- AWS Open Data Registry. CMS DE-SynPUF in OMOP Common Data Model. https://registry.opendata.aws/cmsdesynpuf-omop/
附录 D:一句判断的十条依据
| 序 | 依据 | 指向哪条边界 |
|---|---|---|
| 1 | 官方称全部受益人皆合成 | 不能推断个体 |
| 2 | 官方称变量间的协变被改变 | 不能推断多变量关系 |
| 3 | 官方称单变量统计与回归系数有偏 | 不能报效应量 |
| 4 | 变量数被削减 | 不能替代真实数据做精细分析 |
| 5 | 只含按服务付费 | 不能代表全部参保人 |
| 6 | 以 2008 年样本为种子 | 不能外推到之后入组的人 |
| 7 | 年份止于 2010、编码为 ICD-9 | 不能接 ICD-10 之后的序列 |
| 8 | 稀有记录被抑制 | 不能做罕见事件研究 |
| 9 | 金额经过粗化 | 不能做费用推断 |
| 10 | 2010 年记录量构造性下降 | 不能做趋势解读 |
附录 E:如果只记五件事
- 它是合成的:约两百多万名受益人,没有一个对应真实的人。
- 它能跑通流程:结构、变量名、编码体系都对齐真实 Medicare 理赔。
- 它不能算人群:单变量统计与回归系数官方明确说是有偏的。
- 它止于 2010 年:ICD-9 时代,不能接 ICD-10 之后的数据。
- 它免费且无需协议:二十个样本按需下载,也是它持续被使用的根本原因。
编辑说明
本篇为数据集词条的百科写法,只收录规模、结构、边界三类数字;分布类统计(百分位、直方图、字段取值频次)不在收录范围,属使用者在获得数据后自行完成的一步。
核验时间:2026-10-29。核验方式:以 CMS 官方总述页、DE-SynPUF 专项页、Codebook 与用户手册为主要依据;官方站点主页面存在访问限制,正文所引官方表述取自公开的页面缓存与官方文档片段,数字以专项页记录数表为准。第三方工程信息(OMOP 镜像、Sentinel 转换包)仅用于说明使用生态,不作为数据性质的依据。
未覆盖内容:合成算法的具体参数、各年份差异化处理规则、二十个样本各自的精确人数。这些内容官方未逐项公开,本篇不作估计。
与库内同源档案的分工:CMS DE-SynPUF 档案侧重工程实现与模型转换,本篇侧重合成性质与推断边界,两篇字段口径一致,可交叉阅读。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- mimicel — 共享标签:公共卫生与流行病学 / 电子健康记录
- mimiciii-demo — 共享标签:公共卫生与流行病学 / 电子健康记录
- mimiciv — 共享标签:公共卫生与流行病学 / 电子健康记录
- snds — 共享标签:公共卫生与流行病学 / 电子健康记录 / 医保理赔
- meps — 共享标签:公共卫生与流行病学 / 电子健康记录 / 医保理赔
- healthdata-gov — 共享标签:公共卫生与流行病学 / 医保理赔
- hcup-nis — 共享标签:电子健康记录 / 医保理赔
- cms-de-synpuf — 共享标签:公共卫生与流行病学 / 医保理赔
- nhis-nhid — 共享标签:公共卫生与流行病学 / 电子健康记录 / 医保理赔
- marketscan — 共享标签:公共卫生与流行病学 / 电子健康记录 / 医保理赔
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

