"Periodic" data refers to data which is consistently interfaced from bedside vital signs monitors into eCareManager. Data are generally interfaced as 1 minute averages, and archived into the vitalPeriodic table as 5 minute median values.
The vital signs are not validated by care staff, so data quality can vary, but the use of 1 minute averages followed by 5 minute medians before archival removes many spurious readings.
In [1]:
# Import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import psycopg2
import getpass
import pdvega
# for configuring connection
from configobj import ConfigObj
import os
%matplotlib inline
In [2]:
# Create a database connection using settings from config file
config='../db/config.ini'
# connection info
conn_info = dict()
if os.path.isfile(config):
config = ConfigObj(config)
conn_info["sqluser"] = config['username']
conn_info["sqlpass"] = config['password']
conn_info["sqlhost"] = config['host']
conn_info["sqlport"] = config['port']
conn_info["dbname"] = config['dbname']
conn_info["schema_name"] = config['schema_name']
else:
conn_info["sqluser"] = 'postgres'
conn_info["sqlpass"] = ''
conn_info["sqlhost"] = 'localhost'
conn_info["sqlport"] = 5432
conn_info["dbname"] = 'eicu'
conn_info["schema_name"] = 'public,eicu_crd'
# Connect to the eICU database
print('Database: {}'.format(conn_info['dbname']))
print('Username: {}'.format(conn_info["sqluser"]))
if conn_info["sqlpass"] == '':
# try connecting without password, i.e. peer or OS authentication
try:
if (conn_info["sqlhost"] == 'localhost') & (conn_info["sqlport"]=='5432'):
con = psycopg2.connect(dbname=conn_info["dbname"],
user=conn_info["sqluser"])
else:
con = psycopg2.connect(dbname=conn_info["dbname"],
host=conn_info["sqlhost"],
port=conn_info["sqlport"],
user=conn_info["sqluser"])
except:
conn_info["sqlpass"] = getpass.getpass('Password: ')
con = psycopg2.connect(dbname=conn_info["dbname"],
host=conn_info["sqlhost"],
port=conn_info["sqlport"],
user=conn_info["sqluser"],
password=conn_info["sqlpass"])
query_schema = 'set search_path to ' + conn_info['schema_name'] + ';'
In [3]:
patientunitstayid = 145467
In [4]:
query = query_schema + """
select *
from vitalperiodic
where patientunitstayid = {}
order by observationoffset
""".format(patientunitstayid)
df = pd.read_sql_query(query, con)
df.set_index('observationoffset', inplace=True)
df.sort_index(inplace=True)
df.head()
Out[4]:
In [5]:
df.columns
Out[5]:
In [7]:
# list of columns to plot
vitals = ['temperature', 'sao2', 'heartrate', 'respiration',
'systemicsystolic', 'systemicdiastolic', 'systemicmean']
df[vitals].vgplot.line()
As we can see most data is fairly consistent but there are a few clear outliers for respiration likely due to artifacts around the 2000 minute mark.
In [10]:
# list of columns to plot
vitals = ['cvp', 'pasystolic', 'padiastolic', 'pamean']
df[vitals].vgplot.line()
Though rare, this patient appears to have pulmonary artery monitoring which ceases at around the 1200 minute mark. This also coincides with a large increase in measured central venous pressure (CVP), which is probably related to the catheter removal.
In [12]:
# list of columns to plot
vitals = ['st1', 'st2', 'st3']
# no 'icp' data
df[vitals].vgplot.line()
Machine derived ST segment levels are also available - quantization of the value is done at 0.1 mV and is readily observable.
In [13]:
query = query_schema + """
with t as
(
select distinct patientunitstayid
from vitalperiodic
)
select
pt.hospitalid
, count(distinct pt.patientunitstayid) as number_of_patients
, count(distinct t.patientunitstayid) as number_of_patients_with_tbl
from patient pt
left join t
on pt.patientunitstayid = t.patientunitstayid
group by pt.hospitalid
""".format(patientunitstayid)
df = pd.read_sql_query(query, con)
df['data completion'] = df['number_of_patients_with_tbl'] / df['number_of_patients'] * 100.0
df.sort_values('number_of_patients_with_tbl', ascending=False, inplace=True)
df.head(n=10)
Out[13]:
In [14]:
df[['data completion']].vgplot.hist(bins=10,
var_name='Number of hospitals',
value_name='Percent of patients with data')
Most hospitals in eICU have good data coverage for the vitalperiodic table.