DPCビッグデータ分析

脳卒中医療技術評価と傾向スコアマッチング法

リアルワールドエビデンスの生成

DPCデータベースを活用して、実臨床での医療技術の効果と安全性を評価する手法を学びます。傾向スコアマッチング法から生存分析、医療技術評価まで、包括的な分析手順を習得しましょう。

📊

ビッグデータ処理

全国の約1,700病院、年間1,000万件超の入院データを効率的に処理・分析する手法

⚖️

傾向スコアマッチング

観察研究での選択バイアスを制御し、因果効果を適切に推定する統計手法

⏱️

生存分析

再入院や死亡までの時間を分析し、医療技術の長期効果を評価

💰

医療技術評価

費用対効果分析により、新しい医療技術の経済的価値を定量化

1. DPCデータベースの概要

DPC(Diagnosis Procedure Combination)制度

  • 診断群分類別包括評価制度:診断名と手術・処置の組み合わせによる定額払い制度
  • 2003年から段階的導入、現在約1,700病院が参加
  • 全入院患者の約50%をカバーする国内最大の医療データベース
1

データの特徴

  • 網羅性: 参加病院の全入院患者をカバー
  • 標準化: 統一的な診断・手術・処置コード
  • 経時性: 入院日毎の詳細な医療行為データ
  • 匿名性: 個人識別情報を除去した匿名化データ

脳卒中関連DPCコード例

  • 脳梗塞: 010060xx (発症3日以内/その他/JCS別)
  • 脳出血: 010040xx (JCS別/手術の有無)
  • くも膜下出血: 010030xx (JCS別/手術の有無)
  • リハビリテーション: H000-H003 (脳血管疾患等リハビリ)
2

データ取得プロセス

  1. 研究計画書の作成: 詳細な分析計画と期待される成果
  2. 倫理審査: 所属機関の倫理審査委員会での承認
  3. 利用申請: 厚労科研費等の研究班での利用申請
  4. データ提供: 匿名化された集計データの受領
R - 分析環境の構築
# 必要なパッケージのインストール
install.packages(c("dplyr", "MatchIt", "survival", "survminer", 
                   "tableone", "ggplot2", "lubridate"))

# ライブラリの読み込み
library(dplyr)
library(MatchIt)      # 傾向スコアマッチング
library(survival)     # 生存分析
library(tableone)     # 記述統計表作成
library(ggplot2)      # 可視化

2. データクリーニングと前処理

SQL - 脳卒中コホートの抽出
-- 急性期脳卒中患者の抽出 SELECT * FROM dpc_data WHERE -- 脳梗塞、脳出血、くも膜下出血 (SUBSTR(dpc_code,1,6) IN ('010060', '010040', '010030')) AND age >= 18 -- 成人のみ AND admission_type IN (1,2,3) -- 緊急・救急入院 AND los >= 1 -- 在院日数1日以上 AND discharge_status IS NOT NULL; -- 転帰情報あり

標準的除外基準

  • 重複入院: 同一患者の複数入院の処理方針
  • 転院症例: 急性期→回復期の連続性評価
  • 死亡症例: アウトカムに応じた取扱い決定
  • データ品質: 主要変数に重大な欠損がある症例
R - アウトカム変数の定義
# 在院日数カテゴリ data$los_category <- cut(data$length_of_stay, breaks = c(0, 7, 14, 30, Inf), labels = c("短期", "中期", "長期", "超長期")) # 30日再入院フラグ data$readmission_30d <- ifelse(data$days_to_readmission <= 30 & !is.na(data$days_to_readmission), 1, 0) # 在宅復帰率 data$home_discharge <- ifelse(data$discharge_destination == "home", 1, 0) # リハビリテーション強度 data$rehab_intensity <- data$total_rehab_units / data$length_of_stay # 併存症指標の作成(Charlson Comorbidity Index) data$cci_score <- data$dm + data$copd + data$chf + data$cad + data$ckd*2 + data$cancer*3 # 重み付けスコア

3. 傾向スコアマッチング法

傾向スコアの定義

傾向スコア e(X) = P(T=1|X) は、共変量 X が与えられたときの処置(T=1)を受ける確率です。

重要な性質:
  1. バランシング性質: 傾向スコアが同じ個体間では、共変量分布が処置群・対照群で同一
  2. 強い無関心性: 傾向スコアで条件づけることで処置割り当てが無作為化

因果効果の推定

  • ATE (Average Treatment Effect): 集団全体での平均処置効果
  • ATT (Average Treatment Effect on the Treated): 処置群での平均処置効果
  • ATC (Average Treatment Effect on the Controls): 対照群での平均処置効果
R - ロジスティック回帰による推定
# 傾向スコアモデルの構築 ps_model <- glm(early_rehab ~ age + gender + severity_score + cci_score + hospital_volume + stroke_type + admission_jcs, family = binomial(link = "logit"), data = stroke_data) # 傾向スコアの算出 stroke_data$propensity_score <- predict(ps_model, type = "response") # 傾向スコア分布の確認 library(ggplot2) ggplot(stroke_data, aes(x = propensity_score, fill = factor(early_rehab))) + geom_histogram(alpha = 0.7, position = "identity", bins = 30) + labs(title = "傾向スコアの分布", x = "傾向スコア", y = "度数")
R - 1:1最近傍マッチング
library(MatchIt) # 基本的な1:1マッチング matched_data <- matchit(early_rehab ~ age + gender + severity_score + cci_score + hospital_volume + stroke_type + admission_jcs, data = stroke_data, method = "nearest", distance = "logit", caliper = 0.25 * sd(stroke_data$propensity_score)) # マッチング結果の確認 summary(matched_data) plot(matched_data) # マッチ後データの抽出 matched_df <- match.data(matched_data)
R - 標準化平均差(SMD)の計算
# マッチング前後の共変量バランス評価 library(tableone) # マッチング前 table1_before <- CreateTableOne(vars = covariates, strata = "early_rehab", data = stroke_data, test = FALSE) print(table1_before, smd = TRUE) # マッチング後 table1_after <- CreateTableOne(vars = covariates, strata = "early_rehab", data = matched_df, test = FALSE) print(table1_after, smd = TRUE) # Love plotによる可視化 library(cobalt) love.plot(matched_data, stats = c("mean.diffs", "variance.ratios"), thresholds = c(m = 0.1, v = 2), binary = "std", abs = TRUE, var.order = "unadjusted")

4. 生存分析

R - 再入院までの時間分析
library(survival) library(survminer) # 生存データの作成 stroke_data$time_to_readmission <- ifelse(stroke_data$readmission_30d == 1, stroke_data$days_to_readmission, 30) stroke_data$readmission_event <- stroke_data$readmission_30d # Kaplan-Meier推定 km_fit <- survfit(Surv(time_to_readmission, readmission_event) ~ early_rehab, data = matched_df) # 生存曲線の描画 ggsurvplot(km_fit, data = matched_df, pval = TRUE, conf.int = TRUE, risk.table = TRUE, xlab = "退院後日数", ylab = "再入院回避率", title = "早期リハビリの再入院予防効果") # Log-rank検定 survdiff(Surv(time_to_readmission, readmission_event) ~ early_rehab, data = matched_df)
R - Cox回帰分析
# 単変量Cox回帰 cox_simple <- coxph(Surv(time_to_readmission, readmission_event) ~ early_rehab, data = matched_df) summary(cox_simple) # 多変量Cox回帰(必要に応じて残存交絡の調整) cox_adjusted <- coxph(Surv(time_to_readmission, readmission_event) ~ early_rehab + age + severity_score, data = matched_df) summary(cox_adjusted) # 比例ハザード性の確認 cox.zph(cox_adjusted) # ハザード比の可視化 forest_model(cox_adjusted)

5. 医療技術評価(HTA)

R - DPCデータでの費用算出
# 入院費用の算出 calculate_hospitalization_cost <- function(data) { # DPC包括点数 + 出来高部分 data$dpc_cost <- data$dpc_points * 10 # 1点=10円 data$fee_for_service_cost <- data$additional_procedures * 10 data$total_cost <- data$dpc_cost + data$fee_for_service_cost # 患者負担と保険者負担の分離 data$patient_cost <- data$total_cost * data$copayment_rate data$insurance_cost <- data$total_cost - data$patient_cost return(data) } # QALYの推定(EQ-5Dデータがない場合のマッピング) estimate_qaly <- function(data) { # 在院日数と重症度からQOL低下を推定 qol_baseline <- 0.8 # 健康時のQOL qol_acute <- 0.3 # 急性期のQOL qol_recovery_rate <- 0.1 # 日当たり回復率 data$qaly_loss <- (qol_baseline - qol_acute) * data$length_of_stay / 365.25 return(data) }
R - 増分費用効果比(ICER)の算出
calculate_icer <- function(intervention_group, control_group) { # 平均費用の差 cost_diff <- mean(intervention_group$total_cost) - mean(control_group$total_cost) # 平均効果の差(QALY) effect_diff <- mean(intervention_group$qaly_gain) - mean(control_group$qaly_gain) # ICER計算 icer <- cost_diff / effect_diff # ブートストラップによる信頼区間 bootstrap_icer <- replicate(1000, { boot_int <- sample_n(intervention_group, nrow(intervention_group), replace = TRUE) boot_ctrl <- sample_n(control_group, nrow(control_group), replace = TRUE) boot_cost_diff <- mean(boot_int$total_cost) - mean(boot_ctrl$total_cost) boot_effect_diff <- mean(boot_int$qaly_gain) - mean(boot_ctrl$qaly_gain) boot_cost_diff / boot_effect_diff }) return(list( icer = icer, ci_lower = quantile(bootstrap_icer, 0.025, na.rm = TRUE), ci_upper = quantile(bootstrap_icer, 0.975, na.rm = TRUE) )) }

実践デモ:傾向スコアマッチング

早期リハビリテーションの効果を傾向スコアマッチングで評価してみましょう

マッチング結果

0
マッチ成功ペア数
0%
マッチ率
0%
バランス改善度
0
推定治療効果

結果の解釈がここに表示されます。

DPCビッグデータ分析 理解度クイズ