Elective surgery notebook

This notebook examines three definitions of surgery:

  1. CPT codes
  2. ICD-9 procedure codes
  3. Service type

The aim of this is to facilitate defining elective surgery.


In [1]:
# Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import psycopg2

# used to calculate AUROC/accuracy
from sklearn import metrics


%matplotlib inline

In [2]:
# create a database connection
sqluser = 'postgres'
dbname = 'mimic'
schema_name = 'mimiciii'

# Connect to local postgres version of mimic
con = psycopg2.connect(dbname=dbname, user=sqluser)
cur = con.cursor()

Service type

First we examine if an ICU stay ever occurs before the first service.


In [3]:
cur.execute('SET search_path to ' + schema_name)
query = \
"""
select ie.icustay_id, ie.hadm_id
    , adm.admittime
    , ie.intime
    , min(transfertime) as FirstService
    , min(transfertime) - adm.admittime as DeltaAdmit
    , min(transfertime) - ie.intime as DeltaIn
from icustays ie 
inner join admissions adm
    on ie.hadm_id = adm.hadm_id
left join services se 
    on ie.hadm_id = se.hadm_id
group by ie.icustay_id, ie.hadm_id, ie.intime, adm.admittime
having (min(transfertime)) > intime;
"""

data = pd.read_sql_query(query,con)
data


Out[3]:
icustay_id hadm_id admittime intime firstservice deltaadmit deltain
0 209779 147891 2118-10-24 23:34:00 2118-10-25 11:38:16 2118-10-31 07:29:24 6 days 07:55:24 5 days 19:51:08
1 212553 161640 2147-07-25 15:52:00 2147-07-26 17:02:42 2147-07-27 11:09:39 1 days 19:17:39 0 days 18:06:57
2 225953 140615 2150-07-07 16:13:00 2150-07-09 11:43:25 2150-07-14 10:31:11 6 days 18:18:11 4 days 22:47:46
3 247562 168715 2106-10-08 20:55:00 2106-10-14 19:44:19 2106-10-16 04:37:30 7 days 07:42:30 1 days 08:53:11
4 284459 102005 2177-03-29 00:49:00 2177-04-04 05:49:00 2177-04-10 06:47:00 12 days 05:58:00 6 days 00:58:00

Looks like we have 5 cases where the first service occurs between 1-6 days after the first ICU admission.


In [4]:
# extract surgery definitions using the three methods
cur.execute('SET search_path to ' + schema_name)
query = \
"""
WITH serv as
(
  -- note, 80% of patients only ever have one service
  -- also note, it is possible a patient's trajectory is like this:
  --  1. elective admission
  --  2. medical service
  --  3. ICU admission
  --  4. change to surgical service
  -- we do *not* treat this as an elective surgery

  select ie.icustay_id
    , se.curr_service
    , case when lower(curr_service) like '%surg%' then 1 else 0 end as surgical
    , ROW_NUMBER() over
    (
      PARTITION BY ICUSTAY_ID
      ORDER BY TRANSFERTIME
    ) as serviceOrder
  from icustays ie
  left join services se
    on ie.hadm_id = se.hadm_id
)
, cpt as
(
  select cpt.hadm_id
    , max(case when surgeryflag = 2 then 1 else 0 end) as surgical
  from cptevents cpt
  left join surgeryflag_cpt cptflg
    on cpt.cpt_number between cptflg.cptstart and cptflg.cptstop
  group by cpt.hadm_id
)
, icd as
(
  select icd.hadm_id
    , max(case when surgeryflag = 2 then 1 else 0 end) as surgical
  from procedures_icd icd
  left join surgeryflag_icd9 flg
    on icd.icd9_code = flg.icd9_code
  group by icd.hadm_id
)
select
  ie.subject_id, ie.hadm_id, ie.icustay_id

  , adm.ADMISSION_TYPE

  , cpt.surgical as surgical_cpt
  , icd.surgical as surgical_icd
  , serv.surgical as surgical_service
from icustays ie
-- it's useful to get admission type
inner join admissions adm
  on ie.hadm_id = adm.hadm_id
-- get CPT codes associated with surgery
left join cpt
  on ie.hadm_id = cpt.hadm_id

-- get ICD codes associated with surgery
left join icd
  on ie.hadm_id = icd.hadm_id

-- get first service
left join serv
  on ie.icustay_id = serv.icustay_id and serv.serviceOrder = 1
""" 


data = pd.read_sql_query(query,con)
data.head().T


Out[4]:
0 1 2 3 4
subject_id 29052 31189 86645 26438 13786
hadm_id 185131 144019 164444 187342 190267
icustay_id 231712 286281 234312 286085 223101
admission_type EMERGENCY URGENT EMERGENCY NEWBORN NEWBORN
surgical_cpt 0 0 1 NaN NaN
surgical_icd 0 1 1 1 1
surgical_service 0 1 1 0 0

In [5]:
cur.close()
con.close()

In [6]:
data.shape


Out[6]:
(61532, 7)

In [7]:
print('% surgical status: {:2.2f}% - CPT.').format(100*data.surgical_cpt.mean())
print('% surgical status: {:2.2f}% - ICD.').format(100*data.surgical_icd.mean())
print('% surgical status: {:2.2f}% - SERVICE.').format(100*data.surgical_service.mean())


% surgical status: 21.43% - CPT.
% surgical status: 52.58% - ICD.
% surgical status: 24.64% - SERVICE.