Chuyển đến nội dung chính

第 13 課:ACHILLES — 資料表徵與來源分析

安裝 ACHILLES、在 CDM 上執行資料特徵、分析報告(人口統計、條件、藥物、觀察結果)、ACHILLES Heel — 偵測資料錯誤、在 ATLAS 中整合資料來源。

🏗️ 建築 — 第 13 課 第 13 課:阿基里斯 — 資料表徵和 來源分析

OHDSI 和 OMOP CDM — 綜合醫療數據分析

第 5 部分:資料品質與進階分析

亞洲開發網

第 13 課:ACHILLES — 資料表徵與來源分析

簡介

ACHILLES(大規模縱向證據系統健康資訊的自動表徵)是一種為 CDM 資料庫建立描述性統計資料的工具。 ACHILLES 結果顯示在 ATLAS 資料來源中,有助於在分析之前了解資料。

Vai trò ACHILLES trong workflow:

ETL → CDM Database → ┬→ ACHILLES ─→ Data Sources (ATLAS)
                      │              "Dữ liệu trông thế nào?"
                      │
                      ├→ DQD ──────→ Data Quality Report
                      │              "Dữ liệu có đúng không?"
                      │
                      └→ Analysis ─→ Cohort, Estimation, Prediction
                                     "Dữ liệu nói gì?"

1. 安裝阿基里斯

1.1 要求

- R ≥ 4.0
- Java Runtime (cho DatabaseConnector / JDBC)
- CDM database đã có data
- WebAPI đã cấu hình source

1.2 安裝R套件

# Cài từ GitHub
install.packages("remotes")
remotes::install_github("OHDSI/Achilles")

# Dependencies sẽ tự cài:
#   DatabaseConnector, SqlRender, ParallelLogger

1.3 設定連接

library(Achilles)
library(DatabaseConnector)

connectionDetails <- createConnectionDetails(
  dbms = "postgresql",
  server = "localhost/ohdsi",
  user = "ohdsi_app",
  password = keyring::key_get("ohdsi_password"),
  port = 5432
)

# Kiểm tra kết nối
conn <- connect(connectionDetails)
querySql(conn, "SELECT COUNT(*) FROM cdm.person")
disconnect(conn)

2. 運行阿基里斯

2.1 完整運行

achilles(
  connectionDetails = connectionDetails,
  cdmDatabaseSchema = "cdm",
  resultsDatabaseSchema = "results",
  vocabDatabaseSchema = "cdm",
  sourceName = "Hospital_VN_2024",
  cdmVersion = "5.4",
  createTable = TRUE,
  smallCellCount = 5,          # ẩn cell < 5 (privacy)
  numThreads = 4,
  tempEmulationSchema = NULL
)

2.2 建立ACHILLES表

-- ACHILLES tạo 2 bảng chính trong results schema:

-- 1. achilles_results: aggregate statistics
SELECT * FROM results.achilles_results LIMIT 5;

-- analysis_id  | stratum_1   | stratum_2 | count_value
-- 1            | NULL        | NULL      | 150000      ← tổng patients
-- 2            | NULL        | NULL      | 2500000     ← tổng visits
-- 101          | 8507        | NULL      | 78000       ← male count
-- 101          | 8532        | NULL      | 72000       ← female count
-- 200          | 201826      | NULL      | 45000       ← Type 2 DM count

-- 2. achilles_results_dist: distribution statistics
SELECT * FROM results.achilles_results_dist LIMIT 3;

-- analysis_id | stratum_1 | min  | p10  | p25  | median | p75  | p90  | max
-- 103         | NULL      | 0    | 12   | 25   | 45     | 62   | 78   | 105  ← age dist
-- 203         | 201826    | 1    | 10   | 30   | 90     | 180  | 365  | 3650 ← DM duration

2.3 分析重要ID

Analysis ID  | Mô tả
─────────────┼─────────────────────────────────────────
1            | Number of persons
2            | Number of visits
101          | Gender distribution
103          | Age at first obs distribution
108          | Obs period length distribution
200          | Condition occurrence counts by concept
400          | Condition era counts
700          | Drug exposure counts by concept
800          | Observation counts
1800         | Measurement counts by concept
2100         | Procedure counts by concept

3. ATLAS 中的 ACHILLES 報告

3.1 啟動資料來源

Sau khi chạy ACHILLES:
1. WebAPI tự đọc bảng achilles_results
2. ATLAS → Data Sources → chọn source

Nếu chưa thấy:
  WebAPI → source config → achillesResultsSchema = "results"
  Refresh WebAPI cache

3.2 概覽儀表板

ATLAS → Data Sources → Hospital_VN_2024

┌─────────────────────────────────────────────────────────┐
│  Hospital_VN_2024 — Data Source Report                  │
│                                                         │
│  Persons:      150,000                                  │
│  Records:      12,500,000                               │
│  Obs Period:   2015-01-01 → 2024-12-31                  │
│                                                         │
│  Tabs:                                                  │
│  [Dashboard] [Conditions] [Drugs] [Procedures]          │
│  [Measurements] [Observations] [Visits] [Death]         │
│                                                         │
│  Gender:                                                │
│  ████████████████ Male (52%)                            │
│  ██████████████   Female (48%)                          │
│                                                         │
│  Age Distribution:                                      │
│  0-9:  ██ 8%                                            │
│  10-19: ███ 12%                                         │
│  20-29: █████ 15%                                       │
│  30-39: ██████ 18%                                      │
│  40-49: ████████ 20%                                    │
│  50-59: ██████ 16%                                      │
│  60-69: ███ 7%                                          │
│  70+:   ██ 4%                                           │
└─────────────────────────────────────────────────────────┘

3.3 狀況報告

ATLAS → Data Sources → Conditions

Top 20 Conditions:
┌────┬──────────────────────────────────┬─────────┬────────┐
│ #  │ Condition                        │ Persons │ %      │
├────┼──────────────────────────────────┼─────────┼────────┤
│  1 │ Essential hypertension           │ 45,000  │ 30.0%  │
│  2 │ Type 2 diabetes mellitus         │ 35,000  │ 23.3%  │
│  3 │ Hyperlipidemia                   │ 28,000  │ 18.7%  │
│  4 │ Upper respiratory infection      │ 25,000  │ 16.7%  │
│  5 │ Osteoarthritis                   │ 18,000  │ 12.0%  │
│  6 │ Chronic kidney disease           │ 12,000  │  8.0%  │
│  7 │ Ischemic heart disease           │ 10,000  │  6.7%  │
│  8 │ Depression                       │  8,500  │  5.7%  │
└────┴──────────────────────────────────┴─────────┴────────┘

Drill-down per condition:
  - Prevalence by month (trend over time)
  - Age at first diagnosis distribution
  - Type (inpatient / outpatient / ER)
  - Frequency distribution per person

3.4 藥物報告

ATLAS → Data Sources → Drugs

Drug Exposure by Class (ATC):
┌──────────────────────────────────────────────────┐
│  A10 — Drugs for diabetes                        │
│  ├── Metformin:       25,000 persons             │
│  ├── Glimepiride:      8,000 persons             │
│  ├── Insulin Glargine: 5,000 persons             │
│  └── Empagliflozin:    3,000 persons             │
│                                                  │
│  C09 — ACE Inhibitors & ARBs                     │
│  ├── Enalapril:       15,000 persons             │
│  ├── Losartan:        12,000 persons             │
│  └── Valsartan:        8,000 persons             │
│                                                  │
│  C10 — Lipid Lowering Agents                     │
│  ├── Atorvastatin:    20,000 persons             │
│  ├── Rosuvastatin:    10,000 persons             │
│  └── Simvastatin:      5,000 persons             │
└──────────────────────────────────────────────────┘

Duration distribution, frequency, dosage patterns

4.阿基里斯之踵

4.1 資料品質警告

# ACHILLES Heel chạy tự động cùng achilles()
# Kết quả lưu trong bảng achilles_heel_results

# Xem warnings:
conn <- connect(connectionDetails)
heel <- querySql(conn, "
  SELECT *
  FROM results.achilles_heel_results
  ORDER BY record_count DESC
  LIMIT 20
")
disconnect(conn)

4.2 腳跟警告範例

┌─────┬──────────────────────────────────────────────┬──────────┐
│ ID  │ Warning Message                              │ Severity │
├─────┼──────────────────────────────────────────────┼──────────┤
│   1 │ 5,200 records with date before 1900          │ ERROR    │
│   2 │ 800 persons with age > 150 years             │ ERROR    │
│   3 │ Condition_occurrence has 12% unmapped codes  │ WARNING  │
│   4 │ Drug_exposure end_date < start_date (350)    │ ERROR    │
│   5 │ 15% persons with observation < 30 days       │ WARNING  │
│   6 │ Measurement has no unit_concept_id (25%)     │ WARNING  │
│   7 │ Visit_occurrence has 0 ER visits             │ NOTICE   │
│   8 │ Death records only from 2020+ (COVID bias?)  │ NOTICE   │
└─────┴──────────────────────────────────────────────┴──────────┘

Severity levels:
  ERROR:   Lỗi nghiêm trọng cần fix trước khi phân tích
  WARNING: Vấn đề nên xử lý nhưng không block
  NOTICE:  Thông tin cần kiểm tra

4.3 處理腳跟警告

-- Fix ERROR #1: Records with date before 1900
UPDATE cdm.condition_occurrence
SET condition_start_date = NULL
WHERE condition_start_date < '1900-01-01';

-- Fix ERROR #2: Age > 150
DELETE FROM cdm.person
WHERE EXTRACT(YEAR FROM CURRENT_DATE) - year_of_birth > 150;

-- Fix ERROR #4: end_date < start_date
UPDATE cdm.drug_exposure
SET drug_exposure_end_date = drug_exposure_start_date
WHERE drug_exposure_end_date < drug_exposure_start_date;

-- Sau khi fix: chạy lại ACHILLES

5.增量模式

5.1 讓阿基里斯跑得更快

# Lần đầu: full run (~2-4 giờ cho 1M patients)
# Lần sau: incremental (chỉ update thay đổi)

achilles(
  connectionDetails = connectionDetails,
  cdmDatabaseSchema = "cdm",
  resultsDatabaseSchema = "results",
  sourceName = "Hospital_VN_2024",
  cdmVersion = "5.4",
  createTable = FALSE,       # không tạo lại bảng
  updateGivenAnalysesOnly = TRUE,
  analysisIds = c(1, 101, 200, 700, 1800)  # chỉ update analyses cần
)

5.2 使用 cron 實現自動化

#!/bin/bash
# /opt/ohdsi/scripts/run_achilles.sh

cd /opt/ohdsi/achilles
Rscript -e '
library(Achilles)
library(DatabaseConnector)

connectionDetails <- createConnectionDetails(
  dbms = "postgresql",
  server = Sys.getenv("CDM_DB_SERVER"),
  user = Sys.getenv("CDM_DB_USER"),
  password = Sys.getenv("CDM_DB_PASS"),
  port = 5432
)

achilles(
  connectionDetails = connectionDetails,
  cdmDatabaseSchema = "cdm",
  resultsDatabaseSchema = "results",
  sourceName = "Hospital_VN_2024",
  cdmVersion = "5.4",
  numThreads = 4
)

cat("ACHILLES completed:", format(Sys.time()), "\n")
'
# Chạy ACHILLES hàng tuần (Chủ nhật 2:00 AM)
0 2 * * 0 /opt/ohdsi/scripts/run_achilles.sh >> /var/log/achilles.log 2>&1

總結

成分功能
阿喀琉斯核心計算CDM資料庫的總結統計
阿基里斯結果該表包含計數、盛行率
阿基里斯結果距離包含分佈的表(p10、p25、中位數...)
阿基里斯之踵偵測資料品質問題(錯誤/警告/通知)
ATLAS 資料來源以儀表板格式顯示 ACHILLES 結果
增量模式運轉速度快-只更新變化

下一篇文章:資料品質儀表板 - 評估 CDM 資料質量