-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.qmd
278 lines (207 loc) · 10 KB
/
index.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
---
title: "ICD code を扱う R パッケージ "
author: "nissinbo"
date: "`r Sys.Date()`"
format:
html:
toc: true
toc-location: left
df-print: paged
code-fold: show
code-tools: true
theme: Minty
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(warning = FALSE)
library(tidyverse)
```
::: {.callout-note}
## 略語集
CCI: Charlson Comorbidity Index
GEMs: General Equivalence Mappings
:::
# この資料について
医療情報 DB を用いた研究などでは、ICD code を使って疾患の特定を行うことが多い。
ここでは、ICD code のハンドリングや疾患名の付与、CCI の算出といった作業に便利な R パッケージを紹介する。
::: {.callout-tip}
## ICD code とは
WHO から発出されている**疾病**の分類コード
コードの検索は例えば[icd10data.com](https://www.icd10data.com/) が便利である。
ICD-9, ICD-10 といったバージョン違いの他に、米国では ICD-10-CM が用いられるなど、それらの差異には注意が必要である。
:::
事前準備として tidyverse を読み込んでおく。
```{r eval = FALSE}
library(tidyverse)
```
# [`coder`](https://github.com/ropensci/coder) パッケージ
[rOpenSci](https://ropensci.org/) プロジェクトに入っており、今後も開発が進んでいくことが期待される。
ICD code の他にも薬剤コードの一種である ATC code についても対応している。
```{r}
library(coder)
```
## ICD code を含むサンプルデータ
サンプルデータとして `ex_people`, `ex_icd10`, `ex_atc` が準備されている。
::: {.panel-tabset}
## ex_people
```{r echo=FALSE}
ex_people
```
## ex_icd10
```{r echo=FALSE}
ex_icd10
```
## ex_atc
```{r echo=FALSE}
ex_atc
```
:::
## `categorize()`
`coder` パッケージには、データフレームを結合する `codify()`、併存疾患を抽出する `classify()`、CCI を算出する `index()` という関数があるが、基本的には `categorize()` で一気に行う。
以下では[ドキュメント](https://docs.ropensci.org/coder/)を参考にしたサンプルコードを示す。
```{r}
categorize(
x = ex_people, codedata = ex_icd10,
cc = "charlson", id = "name", code = "icd10")
```
- `x` には重複のない患者 ID 列を含むデータフレームを指定する
- `cc` に入るオプションは以下で確認できる
```{r}
all_classcodes()
```
- `classcodes`: 算出するスコア
- `console` に `?charlson` などと入力してドキュメントを見ると、出自の文献を確認できる
- `console` に `elixhauser` などと入力して Classcodes object から対象疾患を確認できる
- `regex`: 対応するコード(ICD-10 など)
- `indices`: 重みづけの方法
併存疾患を選択するための time window を指定したい場合は、以下のようにする。
```{r}
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日前)
)
)
ch # Time window 中に レコードが 1 つも存在しない場合、スコアは NA となることに注意
# 分布の確認
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`](https://github.com/ellessenne/comorbidity) パッケージ
- 頻繁にレポジトリが更新されており、2022年には CRAN で 1.0.0 がリリースされている。
## 併存疾患の抽出、CCI の算出
`comorbidity()` で ICD code から併存疾患を抽出し、`score()` で CCI を算出する。
以下に [vignette](https://cran.r-project.org/web/packages/comorbidity/vignettes/A-introduction.html) を改変したサンプルコードを示す。
```{r}
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")
```
- CCI は2つの重みづけが利用可能
- [Charlson 1987](https://doi.org/10.1016/0021-9681(87)90171-8)
- [Quan 2011](https://doi.org/10.1093/aje/kwq433)
- Elixhauser Comorbidity Index は2つの重みづけが利用可能
- [van Walraven 2009](https://doi.org/10.1097/mlr.0b013e31819432e5)
- [Sharma 2021](https://doi.org/10.1186/s12913-020-05999-5)
# [`touch`](https://github.com/cran/touch) パッケージ
ICD-9 と ICD-10 の相互変換を行うには、GEMs を用いる方法がある。R で実現するには `touch` パッケージが唯一の選択肢である。
使用する際は [RDocumentation](https://www.rdocumentation.org/packages/touch/) がわかりやすい。
## GEMs とは
### 概要
- CMS.gov が開発した ICD code 変換の対応表
- [2018年版](https://www.cms.gov/Medicare/Coding/ICD10/2018-ICD-10-CM-and-GEMs)が最終確定版
- [GEMs User’s Guide](https://ftp.cdc.gov/pub/health_statistics/nchs/publications/ICD10CM/2018/Dxgem_guide_2018.pdf) や [Documentation for Technical Users](https://ftp.cdc.gov/pub/health_statistics/nchs/publications/ICD10CM/2018/GemsTechDoc_2018.pdf) に変換規則が記載
### GEMs の特徴
- コードの変換は 1:1 マッピング(50%)の他に 1:n, n:1, n:n マッピングや対応がないものもある
- 9→10 (Forward) と 10→9 (Backward) の辞書は鏡像の関係ではない
- [AHIMA](https://library.ahima.org/doc?oid=106975) がわかりやすい
### GEMs を用いた変換に対する批判
GEMs による ICD-9-CM → ICD-10-CM 変換には批判も多く存在するため、注意が必要
- [AHIMA GEMs](https://library.ahima.org/PB/GEMs#.Ylg36ujP200)
- GEMs は単純な crosswalk: 横断歩道ではない
- 1:n の時にすべての値を残すか、妥協点として無理やり 1:1 にするかは目的次第
- 見たい 9-CM が少なければ、GEMs を使う必要はなく、コードを直接検索するのが速く簡単で正確である
- [Reeves 2020](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7059548/)
- GEMsを単独で使用しても、包括的かつ正確には変換できない
- 9-CM と 10-CM の比較可能性を確保するための確実な選択肢は、各コードの手動レビューである
### GEMs を用いた変換の精度を検証した論文
- [Turer 2015](https://academic.oup.com/jamia/article/22/2/417/697375)
- 医療記録のプロが 598 の 9-CM を 10-CM に手動変換 「GEMs と一致したのは85.2%」
- [Columbo 2018](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6501611/)
- 心血管イベントのコードを医師が検証 「GEMs は便利だけど、手動で検証する必要がある」
- [Simeone 2020](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8120674)
- 医師・コーダーが手動変換して検証 「手動のほうが包括的である」
- [Mainor 2020](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6535377/)
- 2015年の 9-CM と 10-CM の切り替え前後で、GEMs で翻訳されたコードの診断頻度が大きく変動していた(=疾患の増減とは考えづらく、変換が不完全であることの現れ)
## ICD-9 と ICD-10 の相互変換
`icd_map()` を使う。
```{r}
library(touch)
icd9codes <- c("0011", "001.1", "316", "29383", "E9808", "V90")
icd_map(icd9codes)
```
- `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`](https://github.com/jackwasey/icd) パッケージ
現在 CRAN に収載されておらず、上記のパッケージで代替できる機能を使う理由は見当たらないが、ICD code から傷病名を付与する `explain_code()` は便利である。
## インストール
CRAN にないため、GitHub からインストールする。
```{r eval=FALSE}
remotes::install_github("jackwasey/icd")
# icd を初めて使う場合は以下を実行する
icd::set_icd_data_dir()
```
## `explain_code()`
```{r}
library(icd)
df_icd10 <- tibble(icdcode = c("A00", "A000", "C63.0", "C64"))
df_icd10 |>
mutate(name = explain_code(icdcode))
```
# まとめ
- rOpenSci の `coder` はシンプルな関数群と、豊富なリファレンスがあることより一押し
- `comorbidity` は、CCI 算出が目的であれば十分
- `icd` は `explain_code()` が他のパッケージで代替できない関数となっている
- GEMs を用いた iCD-9-CM → ICD-10-CM の変換には `touch` が便利