3. 标准词汇表与概念映射
在 OMOP CDM 中,所有临床事件最终都通过一个整数 concept_id 落到 CONCEPT 表上。源系统里的诊断、检验、药品、手术往往使用各自的本地编码或不同标准(ICD-10、院内检验码、商品名药品字典等),因此“把源编码翻译成标准概念”是 ETL 中最关键、也最容易出错的一步。本节聚焦四类最常用的标准词汇表——SNOMED、LOINC、RxNorm、ICD——以及承载映射关系的 CONCEPT 与 CONCEPT_RELATIONSHIP 两张表。
一、CONCEPT 表:标准概念的“身份证”
CONCEPT 表是 OMOP 的词汇中枢,每一行代表一个概念,核心字段包括:
concept_id:全局唯一整数,是事实表中真正存储的值;concept_name:概念名称,如 “Type 2 diabetes mellitus”;domain_id:所属域,如 Condition、Drug、Measurement、Procedure、Observation;vocabulary_id:来源词汇表,如 SNOMED、LOINC、RxNorm、ICD10CM;concept_class_id:概念粒度,如 Clinical Finding、Ingredient、Lab Test;standard_concept:'S'表示标准概念,'C'表示分类概念,空值表示非标准概念;concept_code:源词汇表中的原始编码,如 SNOMED 的 “44054006”。
关键约定是:事实表(CONDITION_OCCURRENCE、DRUG_EXPOSURE、MEASUREMENT 等)中的 *_concept_id 必须指向 standard_concept='S' 的标准概念。ICD-10 编码本身在 OMOP 中通常是非标准概念(standard_concept 为空),它只作为“源编码”存在,需要通过映射关系找到对应的 SNOMED 标准概念。
二、CONCEPT_RELATIONSHIP 表:概念之间的“关系网”
CONCEPT_RELATIONSHIP 描述两个概念之间的有向关系,核心字段为 concept_id_1、concept_id_2、relationship_id。与映射最相关的几类关系是:
Maps to:从非标准概念指向标准概念,是 ETL 映射的主通道;Mapped from:Maps to的反向关系,用于溯源;Is a:层级关系(如具体类型指向更上位概念),用于概念集扩展;Subsumes/Has ingredient/RxNorm has ing:药物成分与临床药物之间的关系。
因此,一条典型的映射查询是:给定源编码,先在 CONCEPT 中按 vocabulary_id 与 concept_code 找到非标准概念,再沿 Maps to 关系取到标准概念。下面这张图展示了四类词汇表到标准概念的映射路径与关系类型。
三、四类词汇表的映射策略
SNOMED CT 是 Condition、Procedure、Observation 域的标准词汇表,本身既是标准概念,也承担大量映射目标。当源系统已使用 SNOMED 时,只需确认 standard_concept='S' 即可直接使用;若源系统使用 ICD-10,则必须走 Maps to。
LOINC 是 Measurement 域的标准词汇表。院内检验码通常先映射到 LOINC,再作为标准概念写入 MEASUREMENT。需要注意 LOINC 概念有“组分—属性—时间—系统—标尺—方法”六轴结构,同一检验项目可能对应多个 LOINC 概念,映射时要结合标本类型与方法学选择。
RxNorm 是 Drug 域的标准词汇表。源药品字典(商品名、院内码)一般先映射到 RxNorm 的 Clinical Drug 或 Ingredient 概念。若研究需要按成分分析,可再通过 RxNorm has ing 关系从临床药概念下钻到 Ingredient 概念。
ICD-10 在 OMOP 中通常是非标准概念,仅作为源编码存在。它的价值在于:很多真实数据只有 ICD 编码,必须依赖官方提供的 ICD→SNOMED 映射关系完成标准化。ICD-9 与 ICD-10 的映射目标可能不同,跨版本分析时要特别小心。
四、实际映射查询怎么写
下面是一段可直接在 OMOP 词汇库上运行的 SQL,演示如何把 ICD-10 编码 E11.9 翻译为标准 SNOMED 概念:
SELECT
src.concept_code AS source_code,
src.concept_name AS source_name,
std.concept_id AS standard_concept_id,
std.concept_name AS standard_name,
std.vocabulary_id AS standard_vocab,
std.domain_id AS standard_domain
FROM concept src
JOIN concept_relationship cr
ON cr.concept_id_1 = src.concept_id
AND cr.relationship_id = 'Maps to'
JOIN concept std
ON std.concept_id = cr.concept_id_2
AND std.standard_concept = 'S'
WHERE src.vocabulary_id = 'ICD10CM'
AND src.concept_code = 'E11.9';
预期结果中,standard_concept_id 指向 SNOMED 的 “Type 2 diabetes mellitus”,standard_domain 为 Condition。若查询返回空行,说明该源编码在词汇表中没有 Maps to 关系,需要人工核查或使用 Mapped from 反向确认。
SELECT vocabulary_id, COUNT(*) FROM concept GROUP BY 1 确认词汇表版本;映射后用 LEFT JOIN 统计未命中率,未命中率超过 5% 时应暂停 ETL 并检查源编码格式(如小数点、大小写、前导零)。
五、常见陷阱与判断依据
- 把非标准概念写入事实表:事实表的
*_concept_id若指向standard_concept为空的概念,后续队列构建会漏掉大量患者。判断方法:对事实表做JOIN concept检查standard_concept='S'的占比。 - 一对多映射未处理:一个 ICD 编码可能
Maps to多个 SNOMED 概念。此时应结合domain_id与临床语义选择,或保留多条映射并在分析层去重。 - 忽略
invalid_reason:CONCEPT与CONCEPT_RELATIONSHIP都有invalid_reason字段,已失效的概念不应再用于新映射,查询时应加invalid_reason IS NULL。 - 跨词汇表混用:LOINC 概念不应出现在 Drug 域,RxNorm 概念不应出现在 Measurement 域。用
domain_id做一致性校验是低成本高收益的检查。
掌握 CONCEPT 与 CONCEPT_RELATIONSHIP 的用法后,后续的队列构建、概念集定义、协变量提取都建立在这一层标准化之上。映射质量直接决定队列的召回率与准确率,因此建议在 ETL 阶段就建立映射日志表,记录每条源编码的命中情况与人工干预记录。