ICD code を扱う R パッケージ

Author

nissinbo

Published

June 23, 2023

略語集

CCI: Charlson Comorbidity Index
GEMs: General Equivalence Mappings

この資料について

医療情報 DB を用いた研究などでは、ICD code を使って疾患の特定を行うことが多い。
ここでは、ICD code のハンドリングや疾患名の付与、CCI の算出といった作業に便利な R パッケージを紹介する。

ICD code とは

WHO から発出されている疾病の分類コード
コードの検索は例えばicd10data.com が便利である。
ICD-9, ICD-10 といったバージョン違いの他に、米国では ICD-10-CM が用いられるなど、それらの差異には注意が必要である。

事前準備として tidyverse を読み込んでおく。

Code
library(tidyverse)

coder パッケージ

rOpenSci プロジェクトに入っており、今後も開発が進んでいくことが期待される。
ICD code の他にも薬剤コードの一種である ATC code についても対応している。

Code
library(coder)

ICD code を含むサンプルデータ

サンプルデータとして ex_people, ex_icd10, ex_atc が準備されている。

categorize()

coder パッケージには、データフレームを結合する codify()、併存疾患を抽出する classify()、CCI を算出する index() という関数があるが、基本的には categorize() で一気に行う。
以下ではドキュメントを参考にしたサンプルコードを示す。

Code
categorize(
  x = ex_people, codedata = ex_icd10, 
  cc = "charlson", id = "name", code = "icd10")
Classification based on: icd10
  • x には重複のない患者 ID 列を含むデータフレームを指定する
  • cc に入るオプションは以下で確認できる
Code
all_classcodes()
  • classcodes: 算出するスコア
    • console?charlson などと入力してドキュメントを見ると、出自の文献を確認できる
    • consoleelixhauser などと入力して Classcodes object から対象疾患を確認できる
  • regex: 対応するコード(ICD-10 など)
  • indices: 重みづけの方法

併存疾患を選択するための time window を指定したい場合は、以下のようにする。

Code
ch <- 
  categorize(
    x = ex_people, codedata = ex_icd10, cc = "charlson", id = "name", code = "icd10",
    index       = c("quan_original", "quan_updated"),  # 同時に複数の重みづけで算出
    codify_args = list(
      date      = "surgery",   # ex_people 中の指標日にあたる列
      code_date = "admission", # ex_icd10 中の診断日にあたる列
      days      = c(-90, -1)   # Time window を指定(この例では1-90日前)
    )
  )
Classification based on: icd10
Code
ch  # Time window 中に レコードが 1 つも存在しない場合、スコアは NA となることに注意
Code
# 分布の確認
ch |> 
  mutate(across(starts_with("quan"), ~replace_na(., 0))) |>   # NA を 0 に変換
  pivot_longer(cols = c(quan_original, quan_updated), names_to = "weight_method", values_to = "score") |> 
  ggplot() +
  aes(score, fill = weight_method) + 
  geom_bar(position = "dodge", width = 0.5)

comorbidity パッケージ

  • 頻繁にレポジトリが更新されており、2022年には CRAN で 1.0.0 がリリースされている。

併存疾患の抽出、CCI の算出

comorbidity() で ICD code から併存疾患を抽出し、score() で CCI を算出する。
以下に vignette を改変したサンプルコードを示す。

Code
library(comorbidity)

# サンプルデータ作成
set.seed(1)
df <- data.frame(
  id = sample(seq(100), size = 10000, replace = TRUE),
  code = sample_diag(n = 100)) |>   # generate ICD-10 code at random
  tibble() |> 
  arrange(id, code)

# CCI の疾患の集計
charlson_df <- df |> 
  comorbidity(id = "id", code = "code", 
              map = "charlson_icd10_quan", assign0 = FALSE)

# CCI の計算
cci_df <- charlson_df |> 
  mutate(id, 
         original_cci = score(charlson_df, weights = "charlson", assign0 = FALSE), 
         quan_cci = score(charlson_df, weights = "quan", assign0 = FALSE), 
         .keep = "none") 

# Elixhauser Comorbidity Index: ECI の疾患の集計
elixhauser_df <- df |> 
  comorbidity(id = "id", code = "code", 
              map = "elixhauser_icd10_quan", assign0 = FALSE)

# ECI の計算
eci_df <- elixhauser_df |> 
  mutate(id, 
         vanwalraven_eci = score(elixhauser_df, weights = "vw", assign0 = FALSE), 
         sharma_eci = score(elixhauser_df, weights = "swiss", assign0 = FALSE), 
         .keep = "none")

touch パッケージ

ICD-9 と ICD-10 の相互変換を行うには、GEMs を用いる方法がある。R で実現するには touch パッケージが唯一の選択肢である。
使用する際は RDocumentation がわかりやすい。

GEMs とは

概要

GEMs の特徴

  • コードの変換は 1:1 マッピング(50%)の他に 1:n, n:1, n:n マッピングや対応がないものもある
  • 9→10 (Forward) と 10→9 (Backward) の辞書は鏡像の関係ではない
  • AHIMA がわかりやすい

GEMs を用いた変換に対する批判

GEMs による ICD-9-CM → ICD-10-CM 変換には批判も多く存在するため、注意が必要

  • AHIMA GEMs
    • GEMs は単純な crosswalk: 横断歩道ではない
    • 1:n の時にすべての値を残すか、妥協点として無理やり 1:1 にするかは目的次第
    • 見たい 9-CM が少なければ、GEMs を使う必要はなく、コードを直接検索するのが速く簡単で正確である
  • Reeves 2020
    • GEMsを単独で使用しても、包括的かつ正確には変換できない
      • 9-CM と 10-CM の比較可能性を確保するための確実な選択肢は、各コードの手動レビューである

GEMs を用いた変換の精度を検証した論文

  • Turer 2015
    • 医療記録のプロが 598 の 9-CM を 10-CM に手動変換 「GEMs と一致したのは85.2%」
  • Columbo 2018
    • 心血管イベントのコードを医師が検証 「GEMs は便利だけど、手動で検証する必要がある」
  • Simeone 2020
    • 医師・コーダーが手動変換して検証 「手動のほうが包括的である」
  • Mainor 2020
    • 2015年の 9-CM と 10-CM の切り替え前後で、GEMs で翻訳されたコードの診断頻度が大きく変動していた(=疾患の増減とは考えづらく、変換が不完全であることの現れ)

ICD-9 と ICD-10 の相互変換

icd_map() を使う。

Code
library(touch)

icd9codes <- c("0011", "001.1", "316", "29383", "E9808", "V90")

icd_map(icd9codes)
[1] "A001"  "A001"  "F54"   "F0630" ""      ""     
  • method で 4 つの変換方法を指定可能
    • gem
      • 9→10 の辞書を用いて 9→10 に変換
      • 多くの論文ではこの方法
    • reverse-gem
      • 10→9 の辞書を用いて 9→10 に変換
    • both
      • forward と reverse-forward の結果の和集合
    • multi-stage
      1. 10→9 の辞書を用いて 9→10 に変換
      2. 1 の結果を 9→10 の辞書を用いて 10→9 に変換
      3. 2 の結果を 10→9 の辞書を用いて 9→10 に変換

icd パッケージ

現在 CRAN に収載されておらず、上記のパッケージで代替できる機能を使う理由は見当たらないが、ICD code から傷病名を付与する explain_code() は便利である。

インストール

CRAN にないため、GitHub からインストールする。

Code
remotes::install_github("jackwasey/icd")

# icd を初めて使う場合は以下を実行する
icd::set_icd_data_dir()

explain_code()

Code
library(icd)

df_icd10 <- tibble(icdcode = c("A00", "A000", "C63.0", "C64"))

df_icd10 |> 
  mutate(name = explain_code(icdcode))

まとめ

  • rOpenSci の coder はシンプルな関数群と、豊富なリファレンスがあることより一押し
  • comorbidity は、CCI 算出が目的であれば十分
  • icdexplain_code() が他のパッケージで代替できない関数となっている
  • GEMs を用いた iCD-9-CM → ICD-10-CM の変換には touch が便利