공개데이터로 CDM 데이터 구축해보기



해당 포스트는 2020년 공개SW개발자센터 글로벌 전문 개발자 지원사업 의 일부로 작성하였습니다.

이번 포스트에서는 앞 포스트 에서 언급하였던 OMOP-CDM 데이터를 직접 구축해보자.

우선 데이터모델의 공개 Repository 에 접속해보자.

확인해보면 각 Database 시스템 별로 테이블을 구축할 수 있는 스크립트로 구성된 것을 볼 수 있다.

데이터를 구축한 의료기관이라면 해당 기관의 데이터를 사용할 수 있겠지만, 그렇지 않은 경우라면 공개된 데이터를 찾아야 한다. OHDSI 에서 직접 안내하는 데이터 를 확인할 수 있다.

A 5% sample (116,352 people) of simulated CMS SynPUF data in CDM Version 5.2.2 format is available to download from the OHDSI Google Drive (for additional details, see the README.md file included in the downloaded zip file):

CMS 는 Center for Medicare & Medicaid Service 의 약자로 미국 보건부 산하의 보건의료재정청으로 보면 된다.
SynPUF 는 Medicare Claims Synthetic Public Use Files (SynPUFs) 의 약자로 미국의 보험청구 데이터를 기반으로 한 가상 데이터이다.

해당 링크에서 바로 zip 파일을 다운 받을 수 있다.

다음으로 CDM Version 에 맞는 Database 를 구축하기 위하여 5.2.2 버전의 CommonDataModel 을 받아보자.

CommonDataModel Repository 를 clone 받고 5.2.2 버전으로 checkout 한다.

git checkout v5.2.2

막상 코드를 열어보면 각 Database 이 스크립트로 구성된 것을 볼 수 있다.

사용할 PostgreSQL 의 폴더에 가면 README.md 파일이 있는 것을 볼 수 있다.

Common-Data-Model / PostgreSQL
=================
This folder contains the SQL scripts for PostgreSQL.
In order to create your instantiation of the Common Data Model, we recommend following these steps:
1. Create an empty schema.
2. Execute the script `OMOP CDM ddl - PostgreSQL.sql` to create the tables and fields.
3. Load your data into the schema.
4. Execute the script `OMOP CDM constraints - PostgreSQL.sql` to add the constraints (primary and foreign keys).
5. Execute the script `OMOP CDM indexes required - PostgreSQL.sql` to add the minimum set of indexes we recommend.
Note: you could also apply the constraints and/or the indexes before loading the data, but this will slow down the insertion of the data considerably.

순서대로 진행해보자.

1. Create an empty schema.

PostgreSQL 에서 새로운 schema 를 만든다.

CREATE SCHEMA synpuf5;

2. Execute the script OMOP CDM ddl - PostgreSQL.sql to create the tables and fields.

psql -U postgres -d ohdsi_cdm -a -f OMOP\ CDM\ ddl\ -\ PostgreSQL.sql

코드를 보면 테이블을 만드는 스크립트임을 알 수 있다.
다만 이 경우 public schema 에 생성되기 때문에 schema 를 지정하기 위해서는 아래와 같은 코드를 추가한다.

SET search_path to synpuf5;

3. Load your data into the schema.

위에서 다운로드 받은 synpuf5 를 입력하는 단계이다. 다운로드 받은 파일과 같은 테이블로 입력하도록 아래와 같이 입력한다.

위 스크립트를 보면 몇 가지 포함되지 않은 파일들 (achilles_*, concept_hierarchy) 이 있는데, 위 단계에서 만들어지지 않은 테이블이기 때문에 제외하였다. (추후 직접 실행하는 부분도 진행 후 공유할 예정이다.)

에러가 발생한다.

COPY concept FROM '~/synpuf5pct_20180710/concept.csv' WITH DELIMITER E'\t' CSV HEADER QUOTE E'\b';
psql:OMOP CDM insert synpuf5 - PostgreSQL.sql:13: ERROR:  value too long for type character varying(255)
CONTEXT:  COPY concept, line 3672285, column concept_name: ""Diagnosis of deep vein thrombosis (DVT) based on >= 1 deep vein thrombosis (DVT) criteria in questi..."

코드를 검색하기 위해서는 ATHENA 를 사용한다.

검색 결과 를 확인해보자.

에러난 코드의 이름이 Diagnosis of deep vein thrombosis (DVT) based on >= 1 deep vein thrombosis (DVT) criteria in question 1.3 (link to Form 126 in "Source" section below) plus signs and symptoms suggestive of pulmonary embolism (PE) (e.g., acute chest pain, dyspnea, …..) 이다.

concept table 을 확인해보자.

ohdsi_cdm=# \d concept
                          Table "synpuf5.concept"
      Column      |          Type          | Collation | Nullable | Default
------------------+------------------------+-----------+----------+---------
 concept_id       | integer                |           | not null |
 concept_name     | character varying(255) |           | not null |
 domain_id        | character varying(20)  |           | not null |
 vocabulary_id    | character varying(20)  |           | not null |
 concept_class_id | character varying(20)  |           | not null |
 standard_concept | character varying(1)   |           |          |
 concept_code     | character varying(50)  |           | not null |
 valid_start_date | date                   |           | not null |
 valid_end_date   | date                   |           | not null |
 invalid_reason   | character varying(1)   |           |          |

concept_nameTEXT NOT NULL 으로 바꿔주자.

ohdsi_cdm=# alter table concept alter column concept_name type text;
ALTER TABLE

다시 concept table 을 확인해보자.

ohdsi_cdm=# \d concept
                          Table "synpuf5.concept"
      Column      |         Type          | Collation | Nullable | Default
------------------+-----------------------+-----------+----------+---------
 concept_id       | integer               |           | not null |
 concept_name     | text                  |           | not null |
 domain_id        | character varying(20) |           | not null |
 vocabulary_id    | character varying(20) |           | not null |
 concept_class_id | character varying(20) |           | not null |
 standard_concept | character varying(1)  |           |          |
 concept_code     | character varying(50) |           | not null |
 valid_start_date | date                  |           | not null |
 valid_end_date   | date                  |           | not null |
 invalid_reason   | character varying(1)  |           |          |

다시 insert 를 하면 데이터가 제대로 들어가는 것을 확인할 수 있다.

관련하여 이미 이슈들이 올라가 있는데, 현재까지 최신버전에서도 255 로 한정되어 있다. (이유를 확인해봐야 할 것 같다.)

4. Execute the script OMOP CDM constraints - PostgreSQL.sql to add the constraints (primary and foreign keys).

psql -U postgres -d ohdsi_cdm -a -f OMOP\ CDM\ constraints\ -\ PostgreSQL.sql

5. Execute the script OMOP CDM indexes required - PostgreSQL.sql to add the minimum set of indexes we recommend.

psql -U postgres -d ohdsi_cdm -a -f OMOP\ CDM\ indexes required\ -\ PostgreSQL.sql

4, 5단계는 3단계까지 진행되었다면 문제없이 진행될 것이다.