แผนการเรียนรู้
/
AMMS 302 | Week 13

Finding Insights from Big Data (II)

OMOP Common Data Model — cohort analytics

person · visit_occurrence · condition_occurrence · measurement · concept vocabulary · ATLAS

🎯 เป้าหมาย (CLO2/CLO4)

  • JOIN core OMOP tables เพื่อสร้าง cohort ได้
  • ค้นโรคด้วย concept/concept_ancestor vocabulary ได้
  • สรุป Table-1 baseline + prevalence แบบ research paper
Lab: 🧪 week13-omop-insights.ipynb — ใช้ omop_mini.db (wk11) หรือ pysynthea prebuilt DB

สารบัญ

01 · OMOP recap — star around person

person
person_id PK · gender_concept_id · year_of_birth
visit_
occurrence
condition_
occurrence
drug_
exposure
measurement
+ death, observation_period, … — ทุกตารางมี person_id FK
🔑 concept_id ทุก clinical field → ชี้ vocabulary table (SNOMED/RxNorm/LOINC mapped)
🌍 network study: query เดียว รันได้บน DB 250+ แห่งทั่วโลก (OHDSI network)

02 · Get an OMOP database — 2 paths

⭐ A: pysynthea package (prebuilt)

# Python ≥3.13!
uv python install 3.13
uv venv --python 3.13
uv add pysynthea duckdb

from pysynthea.setup.setup import *
setup_db(database="small")   # or full (Zenodo)
conn = connect_db("small")

OMOP example DB generated by Synthea™ — realistic longitudinal records

→ PyPI: pysynthea

B: mini-OMOP (จาก wk11 lab)

# omop_mini.db = person +
# condition_occurrence
import duckdb
conn = duckdb.connect("omop_mini.db")

schema ย่อ แต่ฝึก JOIN/GROUP BY ได้เหมือนกัน — notebook รองรับทั้ง 2 path อัตโนมัติ

→ week11 §4 (สร้าง db)

03 · Concept vocabulary — หัวใจของ OMOP

Tableหน้าที่
conceptcatalog ทุก code: concept_id ↔ name/vocabulary
concept_ancestorhierarchy — E11 ลูกหลานทุกระดับ
concept_synonymค้นด้วยชื่อภาษาอื่น
-- หา T2DM concepts
SELECT concept_id, concept_name
FROM concept
WHERE LOWER(concept_name)
      LIKE '%type 2 diabetes%';

Example ids ที่พบบ่อย

  • 201820 = Type 2 DM (ICD10CM E11 mapped)
  • 320128 = Essential HTN (I10)
  • 8507/8532 = Male/Female gender
💡 ไม่ต้องจำ! ใช้ ATLAS search แล้ว copy concept_id — วิธี production จริง

04 · ATLAS — ออกแบบ cohort แบบ click

  1. เปิด atlas-demo.ohdsi.org (public demo DB)
  2. Search tab → พิมพ์ "diabetes" → เห็น concept tree + counts
  3. Cohort Definitions → New → include E11 subtree → ages 40+
  4. Generate → ได้ SQL จริงให้ copy ศึกษา!
search concept define inclusion generate SQL cohort id
SQL ที่ ATLAS generate = template ที่เราฝึกเขียนมือใน ipynb §3–4
ระวัง: demo server ใช้ข้อมูล synthetic — ห้าม upload PHI ลง public ATLAS (wk10!)

05 · Cohort SQL — DM pattern

-- Full CDM:
SELECT DISTINCT co.person_id
FROM condition_occurrence co
JOIN concept c
  ON c.concept_id =
     co.condition_concept_id
WHERE c.concept_id IN (201820)   -- E11
   OR c.concept_ancestor... -- via ancestor

-- Mini-CDM (wk11):
SELECT person_id
FROM condition_occurrence
WHERE condition_concept_name
      LIKE '%Diabetes%';

Pattern checklist

  • cohort = DISTINCT person_id set (1 คน 1 แถว)
  • JOIN concept เพื่อ search ด้วยชื่อ ไม่ hard-code id ทุกที่
  • index era logic: first dx date = MIN(condition_start_date)
-- index date per patient:
SELECT person_id,
       MIN(condition_start_date) idx_dt
FROM condition_occurrence
WHERE condition_concept_id IN (201820)
GROUP BY person_id;

06 · Prevalence & demographics

SELECT
  CASE WHEN gender_concept_id=8507 THEN 'M'
       WHEN gender_concept_id=8532 THEN 'F' END g,
  COUNT(DISTINCT p.person_id) n_all,
  COUNT(DISTINCT co.person_id) n_dm,
  ROUND(100.0*COUNT(DISTINCT co.person_id)
        /COUNT(DISTINCT p.person_id),1) pct_dm
FROM person p
LEFT JOIN condition_occurrence co
       ON co.person_id=p.person_id
      AND co.condition_concept_id IN (201820)
GROUP BY g ORDER BY g;

LEFT JOIN + COUNT(DISTINCT) = prevalence ไม่ double-count

Sanity-check mindset

  • n_dm ≤ n_all เสมอ (ถ้าเกิน = JOIN bug)
  • synthetic prevalence ~30–40% สูงกว่า real world (~10%) — generator design
  • report ต้อง mention data provenance (Synthea-generated)
🎯 นี่คือ skill ที่ project (wk15–16) ต้องใช้: cohort → prevalence table

07 · Table-1 — baseline characteristics

CharacteristicOverall (N=…)SQL building block
Age, mean (sd)58.3 ± 16.2AVG/YEAR(CURDATE)-year_of_birth
Female, %54.1%SUM(gender=8532)/COUNT(*)
T2DM, %31.7%LEFT JOIN cond + pct
HTN, %42.0%concept 320128 join
ipynb §5 build แบบ minimal — production tools: CohortDiagnostics/Characterization (HADES R packages) หรือ ATLAS “Characterizations” tab

08 · Lab สัปดาห์ที่ 13 🧪

  1. §0–1 Connect (pysynthea small หรือ omop_mini.db)
  2. §2 Explore person/visit tables
  3. §3 Diabetes cohort (LIKE หรือ concept_id)
  4. §4 Prevalence by gender (+age decade ถ้า full CDM)
  5. §5 Table-1 baseline summary

📝 Homework 13

  • เลือกโรคอื่น (HTN/Asthma/AF)
  • หา concept_id ผ่าน ATLAS demo search
  • เขียน cohort + prevalence query ส่ง .ipynb (quote concept_id)
Bonus: วาด bar chart prevalence by decade (matplotlib)

09 · แหล่งอ้างอิงทางการ

🏛️ OHDSI official

🧬 Data packages

📬 ติดต่อ

ดร.วิชิต สมบัติ — wichit.s@ubu.ac.th