Классификация пациентов. Часть 3. Подготовка данных.

Мы уже определили наш первый набор предкторов. Это 6 самый популярных измерений, которые представленны числами и имеют указанные в базе единицы измерения. Однако все они предствелнны множеством измерений во времени, своего рода временными рядами. Наше же выборка должна иметь условно вид таблицы.

Рисунок временной ряд для пульса.

Самое простое, что можно придумать это взять среднее значение. В SQL это возвращается функциеей AVG().

Напишем запрос возврашающий среднее значние всех измерений гемоглабина для каждого пациента.


SELECT --hemoglobin
ch.hadm_id
    , AVG(valuenum) as avg_valuenum
FROM
mimiciii.chartevents_sepsisv_d ch
, mimiciii.admissions_sepsisv_d ad
WHERE
ad.hadm_id = ch.hadm_id
AND (ch.itemid = 220228 -- hemoglobin_id
        OR ch.itemid = 814) -- hemoglobin_id
   
GROUP BY ch.hadm_id

Такй запрос возвращает 5265 строк и учитывет оба возможных кода измерения гемоглобина, в то же время он исключает повторы, так как результаты группируются по id обращения/пациента. Это значит, что хотя бы одно измерение гемоглабино есть в базе для 5265 пациентов, что соответсвут полученной нами ранее цифре и позволяет использовать гемоглабин как поулярный предиктор.
Такими же запросами можем проверить осальные выбранные нами измерения. Результаты провери и коды измерений представлены в табилце ниже.


Label itemid1 itemid2 count real count
Hemoglobin 220228 814 5661 5265
Heart Rate 220045 211 5358 5332
Temperature  223761 678 5327 5301
Non Invasive Blood Pressure systolic 220179 455 5303 5279
Non Invasive Blood Pressure diastolic 220180 8441 5302 5275
Non Invasive Blood Pressure mean 220181 456 5302 5279


Некоторые изменения в общем колечстве измерений, конечно есть, но не очень значительные.

Итак, у нас есть запрос, который возрващает срденее знанчеие всех измерений для гемоглобина для каждого пациента за все вермя его обращения. Сделаем 6 таких запросов и соберем их в одну тааблицу. Но предворительно, избавимся условий определяющийх код измерения в поле WHERE. Тем более эти условия содержат числовые коды, что есть потенциал для сложно отсжеливоемой ошибки. 

Сделаем для каждого типа измерения свое представление предстваление. Определине представления измерений Гемоглобина выглядит так:

 SELECT ch.itemid,
    ch.hadm_id,
    ch.value,
    ch.charttime,
    ch.valuenum
   FROM mimiciii.chartevents_sepsisv_d ch
  WHERE ch.itemid = 220228 OR ch.itemid = 814;

Теперь в запросе возвращающем средние значения измерений вместо таблицы chartevents указем наше представление и уберем лишнее условие в поле WHERE. Повторим операцию для всех 6 измерений. 

SELECT --hemoglobin
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
        mimiciii.z_hemoglobin measurment
        , mimiciii.admissions_sepsisv_d ad 
WHERE
        ad.hadm_id = measurment.hadm_id
GROUP BY measurment.hadm_id


Тперь результаты всех этих 6 запросов нужно собрать в одну таблицу, где строки это обращения/пациенты, а столцы это результаты запросов, тоесть срдение значения измерений. Для этого оформим наши запросы как позапросы и поместим в раздел FROM, туда же добавим таблицу обращений, а в поле WHERE установим соответсия по полю hadm_id. 


SELECT
ad.hadm_id
, select_hemoglobin.avg_valuenum as hemoglobin 
, select_heartrate.avg_valuenum as heartrate
, select_temperature.avg_valuenum as temperature
, select_nbpsystolic.avg_valuenum as nbpsystolic
, select_nbpdiastolic.avg_valuenum as NBPdiastolic
, select_nibmean.avg_valuenum as nibmean
FROM
mimiciii.admissions_sepsisv_d ad,
(SELECT --hemoglobin
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
        mimiciii.z_hemoglobin measurment
        , mimiciii.admissions_sepsisv_d ad 
    WHERE
        ad.hadm_id = measurment.hadm_id
GROUP BY measurment.hadm_id
) select_hemoglobin,
(SELECT --heartrate
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
mimiciii.z_heartrate measurment
, mimiciii.admissions_sepsisv_d ad 
    WHERE
        ad.hadm_id = measurment.hadm_id
GROUP BY measurment.hadm_id
)select_heartrate,
(SELECT --temperature
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
        mimiciii.z_hemoglobin measurment
        , mimiciii.admissions_sepsisv_d ad 
    WHERE
        ad.hadm_id = measurment.hadm_id  
GROUP BY measurment.hadm_id
) select_temperature,
(SELECT --nbpsystolic
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
mimiciii.z_nbpsystolic measurment
, mimiciii.admissions_sepsisv_d ad 
    WHERE
        ad.hadm_id = measurment.hadm_id
GROUP BY measurment.hadm_id
) select_nbpsystolic,
(SELECT --nbpdiastolic
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
mimiciii.z_nbpdiastolic measurment
, mimiciii.admissions_sepsisv_d ad 
    WHERE
        ad.hadm_id = measurment.hadm_id
GROUP BY measurment.hadm_id
) select_nbpdiastolic,
(SELECT --nibmean
measurment.hadm_id 
        , AVG(valuenum) as avg_valuenum
FROM
mimiciii.z_nibmean measurment
, mimiciii.admissions_sepsisv_d ad 
    WHERE
        ad.hadm_id = measurment.hadm_id
GROUP BY measurment.hadm_id
) select_nibmean
WHERE 
ad.hadm_id = select_hemoglobin.hadm_id
and ad.hadm_id = select_heartrate.hadm_id
and ad.hadm_id = select_temperature.hadm_id
and ad.hadm_id = select_nbpsystolic.hadm_id
and ad.hadm_id = select_nbpdiastolic.hadm_id
and ad.hadm_id = select_nibmean.hadm_id


Выглядит довольно громоздко, но работает. Возвращает 5211 строк, именно столько обращений попали в пресечение имеющее все 6 типов измерений. 


Теперь нам необходимо промаркировать эти данные классами и добавить значине класса в табилцу таблицу. Мы ранее определились, что попробуем разделять пациентов на выживших и не выживших. Значит первый класс это пациенты с hospital_expire_flag = 1, а второй это пацинеты с  hospital_expire_flag = 0. 

Добавим в поле SELECT строчку ad.hospital_expire_flag as flag и вот у нас есть первая размеченная выборка. 
Теперь нужно внимательно посмотреть на данные: поискать выборы, пропущенные или нулевые знанчения, оценить сбалансированность (соотношение количества представителей каждого класса). 


К выбросам можно отнести средниее значение систолического давления больше 174 
hadm_id nbpsystolic
199515 1613.455
146937 874.5333
124880 339.875
112629 174.913
105518 174.5
183441 169.7872
159164 169.0345
155554 168.0417
183455 167.6184
191707 166.9778
171977 165.5714
176836 165.4
Возможно мы бы смогли отфильтровать еще ряд значений для других измерений, елси бы привлеки специалистов из медицины, которые понимают реальных смысл и возможность этих данных. Конечно, можно также подвергнуть каждый столбец статистическому анализу и получить более чистые данные, но на этом этапе это не требуется, так как стоя нашу первую модель мы пытаемся понять, если ли вообще в этих данных какие-нибудь закономерности. Однако убрать явные выбросы было необходимо, т.к. значние оличающееся в 10 раз в дальнейшем сильно повлияло бы на результат нормализации. 

Кроме того получившийся датасет сильно не сбалансирован. Класс 0 насчитвывает 3970 строк, а Класс 1 - 1537. Для того, чтобы полностью сбалансировать выборку уберем из нее 2433 примера из Класса 0. То какие имеено 2433 примера мы исключим может тоже оказать влияние на качетсво обучения нашей модели. Выберем примеры для исключения случайным образом.

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









Комментарии

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

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

Начало

Complete move of remote Git repository