Классификация пациентов. Часть 2. Отбор признаков

Мы ограничили данные выборкой пациентов у которых в списке диагнозов есть коды сепсиса.
К сепсису относяст ICD9 коды 9959. Значит в запросах нужно добавять что-то вроже 
 WHERE 
      diagnoses_icd.icd9_code like '9959%'

Фото источник: https://icd.codes/icd9cm/9959 

Что бы не писать это условие в коде каждый раз создадим представление для таблиц с коротыми будем работать. Напрмер для таблицы admittions представление будет просто содержать все теже поля, но только те строки для которых есть код сепсиса в теблице diagnoses_icd.

Для справки.
Представления - это таблицы чье содержание выбирается или получается из других таблиц. Они работают в запросах и операторах DML точно также как и основные таблицы, но не содержат ника- ких собственных данных. Представления - подобны окнам, через которые вы просматриваете информа- цию( как она есть, или в другой форме, как вы потом увидите ), которая фактически хранится в базовой таблице. Представление - это фактически запрос, который выполняется всякий раз, когда представление становится темой ко- манды. Вывод запроса при этом в каждый момент становится содержанием представления. Источник:http://www.sql.ru/docs/sql/u_sql/ch20.shtml

Представление для нашего случая 
 SELECT *
 FROM mimiciii.admissions ad
 HERE (ad.hadm_id IN
          ( SELECT di.hadm_id
           FROM mimiciii.diagnoses_icd di
           WHERE di.icd9_code like '9959%'
           GROUP BY di.hadm_id));

Такой запрос возворащает 5395 строк. Значит в нашей выборке теперь 5395 обращений для которых один из котодов диагнозов соответствует сепсису. 

Аналогично представление созадим для самой массивной таблицы БД - chartevents. 

 SELECT *
   FROM mimiciii.chartevents ch
  WHERE (ch.hadm_id IN
           ( SELECT ad.hadm_id
           FROM mimiciii.admissions_sepsisv_d ad
          WHERE ad.has_chartevents_data = 1));


Теперь мы можем обращаться в запросах к этим представлениям такимже синтаксисом как к обчным таблицам, и не перегружать код дополнительными условиями. 

Теперь определим два класса, на которые разделим наших пациентов и которые будем учить нашу модель предсказывать. Самое простое, что можно сделать - разделить пацинетов на тех кто умер в больнице и тех кто остался жив. Эта информация хранится в виде флага hospital_expire_flag в таблице admission. На этом этапе мы не задаемся вопросом практической полезности такой постановки задачи, хотя после некоторых постепенных усложнений она появится. 

Теперь определим параметры пациентов по которым будем предсказывать класс пациентов, в нашем случае останется жив пациент или нет. 

Будем исходить из того, что мы ничего не знаем о заболевании и информативности медицинских показателей, измерений, демографических данных и тд. В таком случае будем исходить из данных, которые у нас есть. 

Для того, что бы получить достаточно большую выборку данных посмотрим какие измперния встречаются чаще.  

Поверхностный обзор таблцы chartevents показывает, что некоторые измерения многократно встречаются у одного пациента. Например пуль или температуру мериют каждые несколько минут. В то время, как есть измерения, которые не встречаются вовсе. Нпомню, всего у нас 12 000 типов измерений. Для нача оставим только те, которые сожержат числовые значения. 
-- для каждого item id который содержить только числовые значения, посчитать сколько раз встречается в chartevents
--

SELECT
    ch.itemid,
    count(*) 
FROM
     mimiciii.chartevents_sepsisv_d ch
    JOIN mimiciii.d_items dt ON dt.itemid = ch.itemid   
WHERE ch.valuenum IS NOT NULL  
GROUP BY
            ch.itemid  
ORDER BY
            ch.itemid

Такой запрос возвращает список из 1626 записи. Это значительно сократило поле поиска. 
  
Кстати, такой же запрос токль из полной таблицы chartevents (а не представления chartevents_sepsisv_d о котором мы написали ранее) возвращает 2884 записей.

Теперь напишем запрос таким образом, что бы почтитать для каждого изметерия у скольки пациентов оно встечается хотя бы один раз.

SELECT 
     select1.itemid
    , select1.label
    , count(*)

FROM 
(SELECT
        ch.hadm_id
        , ch.itemid
        , di.label
    FROM 
        mimiciii.chartevents_sepsisv_d ch
        JOIN 
        mimiciii.d_items di
        ON ch.itemid = di.itemid
     WHERE 
     ch.valuenum IS NOT NULL
    GROUP BY
        ch.hadm_id
        , ch.itemid
        , di.label
 )select1
    
GROUP BY 
    select1.itemid
    , select1.label 
    
ORDER BY count DESC

Первый 20 результатов выглядят так.
 
Уберем отсюда сточки в которых отсутсвую единицы измерения, добавив во внутренний запрос в поле   WHERE 
     ch.valueoum IS NOT NULL




Из результатов видно, что  максимльно ни одно измерение не встечается чаще 3150 раз. Это сильно сокращает нашу выборку. Однако врядли из 5000 пациентов пульс померили только 2914. Действительно, внимательно посмотрев на эту таблицу (полную её версию), можно увдиеть, что некоотрые измерения имеют разные кода. И в части случаев употребляютс с одним кодом (itmeid), в остальных с другим. Вот результат сопоставления некоторых из таких кодов и 30 самым популярных измерений с четом встречаемости с разными кодами.

220228
Hemoglobin
3141
814
Hemoglobin
2520
5661
220045
Heart Rate
2914
211
Heart Rate
2444
5358
223761
Temperature Fahrenheit
2896
678
Temperature F
2431
5327
220179
Non Invasive Blood Pressure systolic
2897
455
NBP [Systolic]
2406
5303
220180
Non Invasive Blood Pressure diastolic
2897
8441
NBP [Diastolic]
2405
5302
220181
Non Invasive Blood Pressure mean
2896
456
NBP Mean
2406
5302
220046
Heart rate Alarm - High
2908
8549
HR Alarm [High]
2277
5185
220047
Heart Rate Alarm - Low
2908
5815
HR Alarm [Low]
2277
5185
223751
Non-Invasive Blood Pressure Alarm - High
2873
8551
NBP Alarm [High]
2194
5067
223752
Non-Invasive Blood Pressure Alarm - Low
2873
5817
NBP Alarm [Low]
2194
5067
226512
Admission Weight (Kg)
2914
762
Admit Wt
2070
4984
220074
Central Venous Pressure
1670
113
CVP
1717
3387
225624
BUN
3150
-
-
-
3150
220615
Creatinine
3150
-
-
-
3150
227073
Anion gap
3149
-
-
-
3149
220602
Chloride (serum)
3149
-
-
-
3149
220621
Glucose (serum)
3149
-
-
-
3149
227443
HCO3 (serum)
3149
-
-
-
3149
227442
Potassium (serum)
3149
-
-
-
3149
220645
Sodium (serum)
3149
-
-
-
3149
220545
Hematocrit (serum)
3143
-
-
-
3143
227457
Platelet Count
3141
-
-
-
3141
220546
WBC
3141
-
-
-
3141
220635
Magnesium
3134
-
-
-
3134
225677
Phosphorous
3132
 -
 -
 -
3132
225625
Calcium non-ionized
3131
 -
 -
 -
3131
220050
Arterial Blood Pressure systolic
1530
51
Arterial BP [Systolic]
1535
3065
220051
Arterial Blood Pressure diastolic
1529
8368
Arterial BP [Diastolic]
1532
3061
224687
Minute Volume
1590
450
Minute Volume(Obser)
1457
3047
220210
Respiratory Rate
2915
 -
 -
2915

Кстати, по поводу разных кодов есть упоминание в документации к базе. В какой системе кодов хранится информация об измерениях указана для каждого пациента. Потенциальная сложность заключается в том, что для некоторых случаев используются обе системы. Тогда каждое измерение с идентичными разультатами будут записано в таблице chartevents дважды. Этим объясняется, почему в выборе из 5395 пациентов гемоглабин измеряли хотя бы раз у 5661. 
Для того, что бы получить максимально большую выборку и как можно меньше пропущеных значений в ней (missing values) мы будем работать с превыми 6 самыми популярными измерениями. Хотя, из за того, что некоторые измерения записаны и посчитанны дважды, числа в правом столбце могут быть не достоверными. Мы исходим из того, что эта погрешность не такая большая, что бы существенно повляить на наш выбор признаков на этом этапе. 

Мы выбрали признаки и ограничили перечень пациентов. Теперь нам нужно получить эти данные из БД. Однако еще одна проблема которая стоит переднами это отображение данных предстваленных в виде многократных повторяющихся измерений. Например пульс измеряется с периодичность в несоклько минут автоматически и каждое измерение вносится в базу.

Эти задачи будут рассмотренны в следующей части.






Комментарии

Популярные сообщения из этого блога

Как узнать день недели для любой даты н.э.

Начало

Complete move of remote Git repository