knitr::opts_chunk$set(warning = FALSE, message = FALSE)
pacman::p_load(
tidyverse,
lubridate,
tableone,
skimr,
duckdb,
DBI,
dbplyr,
arrow,
RSQLite
)
Fドライブの Database フォルダ内にある
mimic_iv.db にアクセスします。
各自の環境に合わせて、必要であれば以下のパスを修正してください。
db_path <- "F:/Database/mimic_iv.db"
duckdb::duckdb() で接続すると、指定した .db
ファイルが存在しない場合は、空のDBファイルが作成されます。
最初に学生自身がMIMIC-IVのCSVをDB化する場合は、この空のDBにテーブルを追加していきます。
con_mimic <- DBI::dbConnect(duckdb::duckdb(), dbdir = db_path)
DB内に入っているテーブルの一覧を確認します。
DBI::dbListTables(con_mimic)
## [1] "admissions" "bja_step01_patients_2026"
## [3] "caregiver" "chartevents"
## [5] "d_hcpcs" "d_icd_diagnoses"
## [7] "d_icd_procedures" "d_items"
## [9] "d_labitems" "datetimeevents"
## [11] "diagnoses_icd" "drgcodes"
## [13] "emar" "emar_detail"
## [15] "hcpcsevents" "icustays"
## [17] "ingredientevents" "inputevents"
## [19] "labevents" "microbiologyevents"
## [21] "omr" "outputevents"
## [23] "patients" "pharmacy"
## [25] "poe" "poe_detail"
## [27] "prescriptions" "procedureevents"
## [29] "procedures_icd" "provider"
## [31] "sepsis3" "services"
## [33] "transfers"
テーブルを削除する場合の例です。通常は実行しません。
# DBI::dbRemoveTable(con_mimic, "caregivers")
最後に接続解除する場合は、以下を使います。
# DBI::dbDisconnect(con_mimic, shutdown = TRUE)
MIMIC-IVのCSVファイルが以下のフォルダに保存されている前提です。
data_path <- "F:/BigDatas/mimic_iv"
MIMIC-IVでは、hosp や icu
などのサブフォルダにCSVファイルが入っています。
そのため、recursive = TRUE を使って、サブフォルダ内の
.csv.gz ファイルもすべて取得します。
csv_list <-
list.files(
path = data_path,
pattern = ".csv.gz$",
recursive = TRUE,
full.names = TRUE
)
csv_list
## [1] "F:/BigDatas/mimic_iv/hosp/admissions.csv.gz"
## [2] "F:/BigDatas/mimic_iv/hosp/d_hcpcs.csv.gz"
## [3] "F:/BigDatas/mimic_iv/hosp/d_icd_diagnoses.csv.gz"
## [4] "F:/BigDatas/mimic_iv/hosp/d_icd_procedures.csv.gz"
## [5] "F:/BigDatas/mimic_iv/hosp/d_labitems.csv.gz"
## [6] "F:/BigDatas/mimic_iv/hosp/diagnoses_icd.csv.gz"
## [7] "F:/BigDatas/mimic_iv/hosp/drgcodes.csv.gz"
## [8] "F:/BigDatas/mimic_iv/hosp/emar.csv.gz"
## [9] "F:/BigDatas/mimic_iv/hosp/emar_detail.csv.gz"
## [10] "F:/BigDatas/mimic_iv/hosp/hcpcsevents.csv.gz"
## [11] "F:/BigDatas/mimic_iv/hosp/labevents.csv.gz"
## [12] "F:/BigDatas/mimic_iv/hosp/microbiologyevents.csv.gz"
## [13] "F:/BigDatas/mimic_iv/hosp/omr.csv.gz"
## [14] "F:/BigDatas/mimic_iv/hosp/patients.csv.gz"
## [15] "F:/BigDatas/mimic_iv/hosp/pharmacy.csv.gz"
## [16] "F:/BigDatas/mimic_iv/hosp/poe.csv.gz"
## [17] "F:/BigDatas/mimic_iv/hosp/poe_detail.csv.gz"
## [18] "F:/BigDatas/mimic_iv/hosp/prescriptions.csv.gz"
## [19] "F:/BigDatas/mimic_iv/hosp/procedures_icd.csv.gz"
## [20] "F:/BigDatas/mimic_iv/hosp/provider.csv.gz"
## [21] "F:/BigDatas/mimic_iv/hosp/services.csv.gz"
## [22] "F:/BigDatas/mimic_iv/hosp/transfers.csv.gz"
## [23] "F:/BigDatas/mimic_iv/icu/caregiver.csv.gz"
## [24] "F:/BigDatas/mimic_iv/icu/chartevents.csv.gz"
## [25] "F:/BigDatas/mimic_iv/icu/d_items.csv.gz"
## [26] "F:/BigDatas/mimic_iv/icu/datetimeevents.csv.gz"
## [27] "F:/BigDatas/mimic_iv/icu/icustays.csv.gz"
## [28] "F:/BigDatas/mimic_iv/icu/ingredientevents.csv.gz"
## [29] "F:/BigDatas/mimic_iv/icu/inputevents.csv.gz"
## [30] "F:/BigDatas/mimic_iv/icu/outputevents.csv.gz"
## [31] "F:/BigDatas/mimic_iv/icu/procedureevents.csv.gz"
DBに登録するときのテーブル名を作成します。
たとえば、hosp/admissions.csv.gz は
admissions、icu/icustays.csv.gz は
icustays になります。
short_list <-
list.files(
path = data_path,
pattern = ".csv.gz$",
recursive = TRUE,
full.names = FALSE
)
name_list <- short_list |>
str_replace_all("\\\\", "/") |> # Windowsの \ を / に統一
basename() |> # hosp/admission.csv.gz → admission.csv.gz
str_remove("\\.csv\\.gz$") |> # admission.csv.gz → admission
str_to_lower()
name_list
## [1] "admissions" "d_hcpcs" "d_icd_diagnoses"
## [4] "d_icd_procedures" "d_labitems" "diagnoses_icd"
## [7] "drgcodes" "emar" "emar_detail"
## [10] "hcpcsevents" "labevents" "microbiologyevents"
## [13] "omr" "patients" "pharmacy"
## [16] "poe" "poe_detail" "prescriptions"
## [19] "procedures_icd" "provider" "services"
## [22] "transfers" "caregiver" "chartevents"
## [25] "d_items" "datetimeevents" "icustays"
## [28] "ingredientevents" "inputevents" "outputevents"
## [31] "procedureevents"
CSVファイルとテーブル名の対応を確認します。
tibble(
csv_file = csv_list,
table_name = name_list
)
## # A tibble: 31 × 2
## csv_file table_name
## <chr> <chr>
## 1 F:/BigDatas/mimic_iv/hosp/admissions.csv.gz admissions
## 2 F:/BigDatas/mimic_iv/hosp/d_hcpcs.csv.gz d_hcpcs
## 3 F:/BigDatas/mimic_iv/hosp/d_icd_diagnoses.csv.gz d_icd_diagnoses
## 4 F:/BigDatas/mimic_iv/hosp/d_icd_procedures.csv.gz d_icd_procedures
## 5 F:/BigDatas/mimic_iv/hosp/d_labitems.csv.gz d_labitems
## 6 F:/BigDatas/mimic_iv/hosp/diagnoses_icd.csv.gz diagnoses_icd
## 7 F:/BigDatas/mimic_iv/hosp/drgcodes.csv.gz drgcodes
## 8 F:/BigDatas/mimic_iv/hosp/emar.csv.gz emar
## 9 F:/BigDatas/mimic_iv/hosp/emar_detail.csv.gz emar_detail
## 10 F:/BigDatas/mimic_iv/hosp/hcpcsevents.csv.gz hcpcsevents
## # ℹ 21 more rows
以下は、MIMIC-IVの .csv.gz
ファイルを1つずつ読み込み、DuckDB上のテーブルとして登録するコードです。
注意:
この処理は、各CSVファイルをDuckDB上の新しいテーブルとして登録する処理です。
同じテーブル名がすでにDB内に存在する場合は、上書きも追記もせず、そのテーブルをスキップする設定にしています。
そのため、同じコードを再実行してもデータが重複して追加されることはありません。
ただし、途中でエラーが出た場合は、一部のテーブルだけが作成済みになっていることがあります。
その場合は、DBI::dbListTables(con_mimic)
で作成済みテーブルを確認してから、再実行してください。
for (i in seq_along(name_list)) {
message("Importing: ", csv_list[i], " -> ", name_list[i])
if (DBI::dbExistsTable(con_mimic, name_list[i])) {
message("Skip existing table: ", name_list[i])
next
}
table_name <- DBI::dbQuoteIdentifier(con_mimic, name_list[i])
file_path <- DBI::dbQuoteString(
con_mimic,
normalizePath(csv_list[i], winslash = "/", mustWork = TRUE)
)
sql <- paste0(
"CREATE TABLE ", table_name,
" AS SELECT * FROM read_csv_auto(",
file_path,
", header = true, quote = '\"', escape = '\"', strict_mode = false, sample_size = -1);"
)
DBI::dbExecute(con_mimic, sql)
}
以下は以前の方法です。処理に時間がかかり、append = TRUE による重複追加の危険があるため、今回は使用しません。
# for (i in seq_along(name_list)) {
#
# message("Importing: ", csv_list[i], " -> ", name_list[i])
#
# callback <- function(df, pos) {
# DBI::dbWriteTable(
# conn = con_mimic,
# name = name_list[i],
# value = df,
# append = TRUE
# )
# }
#
# readr::read_csv_chunked(
# file = csv_list[i],
# callback = readr::DataFrameCallback$new(callback),
# chunk_size = 100000
# )
# }
登録後は、テーブル一覧を再度確認します。
DBI::dbListTables(con_mimic)
## [1] "admissions" "bja_step01_patients_2026"
## [3] "caregiver" "chartevents"
## [5] "d_hcpcs" "d_icd_diagnoses"
## [7] "d_icd_procedures" "d_items"
## [9] "d_labitems" "datetimeevents"
## [11] "diagnoses_icd" "drgcodes"
## [13] "emar" "emar_detail"
## [15] "hcpcsevents" "icustays"
## [17] "ingredientevents" "inputevents"
## [19] "labevents" "microbiologyevents"
## [21] "omr" "outputevents"
## [23] "patients" "pharmacy"
## [25] "poe" "poe_detail"
## [27] "prescriptions" "procedureevents"
## [29] "procedures_icd" "provider"
## [31] "sepsis3" "services"
## [33] "transfers"
(charteventsは4.3億行!)
以降では、MIMIC-IVの基本テーブルを確認します。
テーブル名は、上のDB化コードに従うと、admissions,
patients, icustays になります。
admissions は入院単位のテーブルです。
1人の患者が複数回入院している場合があるため、subject_id
は重複します。
db_ad <- tbl(con_mimic, "admissions")
db_ad |> colnames()
## [1] "subject_id" "hadm_id" "admittime"
## [4] "dischtime" "deathtime" "admission_type"
## [7] "admit_provider_id" "admission_location" "discharge_location"
## [10] "insurance" "language" "marital_status"
## [13] "race" "edregtime" "edouttime"
## [16] "hospital_expire_flag"
db_ad |> count()
## # Source: SQL [?? x 1]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n
## <dbl>
## 1 546028
db_ad |> head(5)
## # Source: SQL [?? x 16]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## subject_id hadm_id admittime dischtime deathtime
## <dbl> <dbl> <dttm> <dttm> <dttm>
## 1 10000032 2.26e7 2180-05-06 22:23:00 2180-05-07 17:15:00 NA
## 2 10000032 2.28e7 2180-06-26 18:27:00 2180-06-27 18:49:00 NA
## 3 10000032 2.57e7 2180-08-05 23:44:00 2180-08-07 17:50:00 NA
## 4 10000032 2.91e7 2180-07-23 12:35:00 2180-07-25 17:55:00 NA
## 5 10000068 2.50e7 2160-03-03 23:16:00 2160-03-04 06:26:00 NA
## # ℹ 11 more variables: admission_type <chr>, admit_provider_id <chr>,
## # admission_location <chr>, discharge_location <chr>, insurance <chr>,
## # language <chr>, marital_status <chr>, race <chr>, edregtime <dttm>,
## # edouttime <dttm>, hospital_expire_flag <dbl>
admissions の行数は入院数です。
一方、subject_id
のユニーク数は患者数に近い値になります。
db_ad |>
distinct(subject_id) |>
count()
## # Source: SQL [?? x 1]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n
## <dbl>
## 1 223452
入院数と患者数を同時に確認します。
db_ad |>
summarise(
n_admissions = n(),
n_subjects = n_distinct(subject_id)
)
## # Source: SQL [?? x 2]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n_admissions n_subjects
## <dbl> <dbl>
## 1 546028 223452
patients は患者単位のテーブルです。
性別、匿名化された年齢情報、死亡日などが含まれます。
db_pt <- tbl(con_mimic, "patients")
db_pt |> colnames()
## [1] "subject_id" "gender" "anchor_age"
## [4] "anchor_year" "anchor_year_group" "dod"
db_pt |> count()
## # Source: SQL [?? x 1]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n
## <dbl>
## 1 364627
db_pt |> head(5)
## # Source: SQL [?? x 6]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## subject_id gender anchor_age anchor_year anchor_year_group dod
## <dbl> <chr> <dbl> <dbl> <chr> <date>
## 1 10000032 F 52 2180 2014 - 2016 2180-09-09
## 2 10000048 F 23 2126 2008 - 2010 NA
## 3 10000058 F 33 2168 2020 - 2022 NA
## 4 10000068 F 19 2160 2008 - 2010 NA
## 5 10000084 M 72 2160 2017 - 2019 2161-02-13
patients では、基本的に subject_id
が患者ごとに一意です。
db_pt |>
summarise(
n_rows = n(),
n_subjects = n_distinct(subject_id)
)
## # Source: SQL [?? x 2]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n_rows n_subjects
## <dbl> <dbl>
## 1 364627 364627
icustays はICU滞在単位のテーブルです。
今回のBJA論文再現ではICU患者を対象とするため、今後の講義で重要になります。
db_icu <- tbl(con_mimic, "icustays")
db_icu |> colnames()
## [1] "subject_id" "hadm_id" "stay_id" "first_careunit"
## [5] "last_careunit" "intime" "outtime" "los"
db_icu |> count()
## # Source: SQL [?? x 1]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n
## <dbl>
## 1 94458
db_icu |> head(5)
## # Source: SQL [?? x 8]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## subject_id hadm_id stay_id first_careunit last_careunit intime
## <dbl> <dbl> <dbl> <chr> <chr> <dttm>
## 1 10000032 29079034 39553978 Medical Intens… Medical Inte… 2180-07-23 14:00:00
## 2 10000690 25860671 37081114 Medical Intens… Medical Inte… 2150-11-02 19:37:00
## 3 10000980 26913865 39765666 Medical Intens… Medical Inte… 2189-06-27 08:42:00
## 4 10001217 24597018 37067082 Surgical Inten… Surgical Int… 2157-11-20 19:18:02
## 5 10001217 27703517 34592300 Surgical Inten… Surgical Int… 2157-12-19 15:42:24
## # ℹ 2 more variables: outtime <dttm>, los <dbl>
ICU stay数、入院数、患者数の違いを確認します。
db_icu |>
summarise(
n_icustays = n(),
n_admissions = n_distinct(hadm_id),
n_subjects = n_distinct(subject_id)
)
## # Source: SQL [?? x 3]
## # Database: DuckDB 1.4.4 [mihara@Windows 10 x64:R 4.5.0/F:\Database\mimic_iv.db]
## n_icustays n_admissions n_subjects
## <dbl> <dbl> <dbl>
## 1 94458 85242 65366
事前課題の内容はスライド参照
作業が終わったら、データベース接続を解除します。
# DBI::dbDisconnect(con_mimic, shutdown = TRUE)