In [1]:
import pandas as pd
import numpy as np
In [2]:
data = pd.read_excel('dataset.xls')
data
Out[2]:
PATIENT_VISIT_IDENTIFIER AGE_ABOVE65 AGE_PERCENTIL GENDER DISEASE GROUPING 1 DISEASE GROUPING 2 DISEASE GROUPING 3 DISEASE GROUPING 4 DISEASE GROUPING 5 DISEASE GROUPING 6 ... TEMPERATURE_DIFF OXYGEN_SATURATION_DIFF BLOODPRESSURE_DIASTOLIC_DIFF_REL BLOODPRESSURE_SISTOLIC_DIFF_REL HEART_RATE_DIFF_REL RESPIRATORY_RATE_DIFF_REL TEMPERATURE_DIFF_REL OXYGEN_SATURATION_DIFF_REL WINDOW ICU
0 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 0-2 0
1 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 2-4 0
2 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... NaN NaN NaN NaN NaN NaN NaN NaN 4-6 0
3 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -1.000000 -1.000000 NaN NaN NaN NaN -1.000000 -1.000000 6-12 0
4 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -0.238095 -0.818182 -0.389967 0.407558 -0.230462 0.096774 -0.242282 -0.814433 ABOVE_12 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1920 384 0 50th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 0-2 0
1921 384 0 50th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 2-4 0
1922 384 0 50th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 4-6 0
1923 384 0 50th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 6-12 0
1924 384 0 50th 1 0.0 0.0 1.0 0.0 0.0 0.0 ... -0.547619 -0.838384 -0.701863 -0.585967 -0.763868 -0.612903 -0.551337 -0.835052 ABOVE_12 0

1925 rows × 231 columns

In [3]:
max_id = data.loc[:, ['PATIENT_VISIT_IDENTIFIER']].max().values[0]
print(f'Max ID: {max_id}')
Max ID: 384
In [4]:
data.iloc[:10,:]
Out[4]:
PATIENT_VISIT_IDENTIFIER AGE_ABOVE65 AGE_PERCENTIL GENDER DISEASE GROUPING 1 DISEASE GROUPING 2 DISEASE GROUPING 3 DISEASE GROUPING 4 DISEASE GROUPING 5 DISEASE GROUPING 6 ... TEMPERATURE_DIFF OXYGEN_SATURATION_DIFF BLOODPRESSURE_DIASTOLIC_DIFF_REL BLOODPRESSURE_SISTOLIC_DIFF_REL HEART_RATE_DIFF_REL RESPIRATORY_RATE_DIFF_REL TEMPERATURE_DIFF_REL OXYGEN_SATURATION_DIFF_REL WINDOW ICU
0 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 0-2 0
1 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 2-4 0
2 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... NaN NaN NaN NaN NaN NaN NaN NaN 4-6 0
3 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -1.000000 -1.000000 NaN NaN NaN NaN -1.000000 -1.000000 6-12 0
4 0 1 60th 0 0.0 0.0 0.0 0.0 1.0 1.0 ... -0.238095 -0.818182 -0.389967 0.407558 -0.230462 0.096774 -0.242282 -0.814433 ABOVE_12 1
5 1 1 90th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 0-2 1
6 1 1 90th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 2-4 1
7 1 1 90th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 4-6 1
8 1 1 90th 1 0.0 0.0 0.0 0.0 0.0 0.0 ... -0.880952 -1.000000 -0.906832 -0.831132 -0.940967 -0.817204 -0.882574 -1.000000 6-12 1
9 1 1 90th 1 0.0 0.0 0.0 0.0 1.0 0.0 ... 0.142857 -0.797980 0.315690 0.200359 -0.239515 0.645161 0.139709 -0.802317 ABOVE_12 1

10 rows × 231 columns

In [5]:
attributes = []

columns = [
    'PATIENT_VISIT_IDENTIFIER',
    'AGE_PERCENTIL',
    'AGE_ABOVE65',
    'DISEASE GROUPING 1',
    'DISEASE GROUPING 2',
    'DISEASE GROUPING 3',
    'DISEASE GROUPING 4',
    'DISEASE GROUPING 5',
    'DISEASE GROUPING 6',
    'OXYGEN_SATURATION_MEDIAN',
    'OXYGEN_SATURATION_MIN',
    'RESPIRATORY_RATE_MIN',
    'RESPIRATORY_RATE_MAX'
]

for i in range(max_id + 1):
    visit_data = data[data['PATIENT_VISIT_IDENTIFIER'] == i]
    selected_attributes = visit_data.loc[i * 5, columns]
    
    icu = visit_data.iloc[:, -1].max()
    
    filtered_data = np.append(selected_attributes.values, icu)
    attributes.append(filtered_data)

print(np.array(attributes))
[[0 '60th' 1 ... -0.5 -0.6363636363636365 1]
 [1 '90th' 1 ... 0.9999999999999998 0.6363636363636365 1]
 [2 '10th' 0 ... nan nan 1]
 ...
 [382 '50th' 0 ... nan nan 1]
 [383 '40th' 0 ... nan nan 0]
 [384 '50th' 0 ... -0.4285714285714286 -0.5757575757575759 0]]
In [6]:
filtered_df = pd.DataFrame(data = attributes, columns = columns + ['ICU'])

to_round = [
    'OXYGEN_SATURATION_MEDIAN',
    'OXYGEN_SATURATION_MIN',
    'RESPIRATORY_RATE_MIN',
    'RESPIRATORY_RATE_MAX'
]

for att in to_round:
    filtered_df.loc[:, [att]] = np.round(filtered_df.loc[:, [att]] * 10)
In [7]:
filtered_df
Out[7]:
PATIENT_VISIT_IDENTIFIER AGE_PERCENTIL AGE_ABOVE65 DISEASE GROUPING 1 DISEASE GROUPING 2 DISEASE GROUPING 3 DISEASE GROUPING 4 DISEASE GROUPING 5 DISEASE GROUPING 6 OXYGEN_SATURATION_MEDIAN OXYGEN_SATURATION_MIN RESPIRATORY_RATE_MIN RESPIRATORY_RATE_MAX ICU
0 0 60th 1 0.0 0.0 0.0 0.0 1.0 1.0 7.0 9.0 -5.0 -6.0 1
1 1 90th 1 0.0 0.0 0.0 0.0 0.0 0.0 10.0 10.0 10.0 6.0 1
2 2 10th 0 0.0 0.0 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 1
3 3 40th 0 0.0 0.0 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 0
4 4 10th 0 0.0 0.0 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
380 380 40th 0 0.0 0.0 0.0 0.0 0.0 0.0 7.0 9.0 -4.0 -5.0 1
381 381 Above 90th 1 0.0 0.0 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 0
382 382 50th 0 0.0 0.0 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 1
383 383 40th 0 0.0 0.0 0.0 0.0 0.0 0.0 NaN NaN NaN NaN 0
384 384 50th 0 0.0 0.0 0.0 0.0 0.0 0.0 8.0 9.0 -4.0 -6.0 0

385 rows × 14 columns

In [8]:
set(filtered_df['OXYGEN_SATURATION_MEDIAN'])
Out[8]:
{nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 3.0,
 5.0,
 7.0,
 nan,
 8.0,
 10.0,
 nan,
 nan,
 nan,
 nan,
 nan,
 2.0,
 4.0,
 9.0,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 6.0,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 1.0,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 -10.0,
 nan,
 nan,
 nan,
 -1.0}
In [9]:
from pgmpy.models import BayesianModel
In [10]:
model = BayesianModel([('ICU', att) for att in columns])
model.nodes()
Out[10]:
NodeView(('ICU', 'PATIENT_VISIT_IDENTIFIER', 'AGE_PERCENTIL', 'AGE_ABOVE65', 'DISEASE GROUPING 1', 'DISEASE GROUPING 2', 'DISEASE GROUPING 3', 'DISEASE GROUPING 4', 'DISEASE GROUPING 5', 'DISEASE GROUPING 6', 'OXYGEN_SATURATION_MEDIAN', 'OXYGEN_SATURATION_MIN', 'RESPIRATORY_RATE_MIN', 'RESPIRATORY_RATE_MAX'))
In [11]:
from pgmpy.estimators import BayesianEstimator, MaximumLikelihoodEstimator

# model.fit(
#     data=filtered_df, 
#     estimator=MaximumLikelihoodEstimator,
#     complete_samples_only=False
# )

model.fit(
    data=filtered_df, 
    estimator=BayesianEstimator,
    prior_type="BDeu",
    equivalent_sample_size=100,
    complete_samples_only=False
)
/usr/local/lib/python3.8/site-packages/pgmpy/estimators/BayesianEstimator.py:154: UserWarning: pseudo count specified with bdeu prior. It will be ignored, use dirichlet prior for specifying pseudo_counts
  warn(
In [12]:
print(model.get_cpds()[10])
+---------------------------------+---------------------+---------------------+
| ICU                             | ICU(0)              | ICU(1)              |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(-10.0) | 0.04251700680272108 | 0.03944020356234096 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(-1.0)  | 0.04251700680272108 | 0.03944020356234096 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(1.0)   | 0.04251700680272108 | 0.03944020356234096 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(2.0)   | 0.04251700680272108 | 0.03944020356234096 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(3.0)   | 0.04251700680272108 | 0.0470737913486005  |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(4.0)   | 0.04251700680272108 | 0.03944020356234096 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(5.0)   | 0.05272108843537414 | 0.06997455470737912 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(6.0)   | 0.08333333333333331 | 0.10050890585241729 |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(7.0)   | 0.2159863945578231  | 0.1615776081424936  |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(8.0)   | 0.20578231292517002 | 0.1997455470737913  |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(9.0)   | 0.13435374149659862 | 0.1615776081424936  |
+---------------------------------+---------------------+---------------------+
| OXYGEN_SATURATION_MEDIAN(10.0)  | 0.05272108843537414 | 0.06234096692111959 |
+---------------------------------+---------------------+---------------------+
In [13]:
from pgmpy.inference import VariableElimination
In [14]:
inference = VariableElimination(model)

print(inference.map_query(['ICU'], evidence={'AGE_ABOVE65': 0 }))
Finding Elimination Order: : 100%|██████████| 12/12 [00:00<00:00, 2429.60it/s]
Eliminating: PATIENT_VISIT_IDENTIFIER: 100%|██████████| 12/12 [00:00<00:00, 170.76it/s]
{'ICU': 0}

In [15]:
y = []
y_pred = []

new_cols = [
#     'PATIENT_VISIT_IDENTIFIER',
    'AGE_PERCENTIL',
    'AGE_ABOVE65',
    'DISEASE GROUPING 1',
    'DISEASE GROUPING 2',
    'DISEASE GROUPING 3',
    'DISEASE GROUPING 4',
    'DISEASE GROUPING 5',
    'DISEASE GROUPING 6',
    'OXYGEN_SATURATION_MEDIAN',
    'OXYGEN_SATURATION_MIN',
    'RESPIRATORY_RATE_MIN',
    'RESPIRATORY_RATE_MAX'
]

for index, row in filtered_df.iterrows():
    y.append(row['ICU'])
    
    data = row[new_cols].dropna()
    
    ev = {}
    for att in new_cols:
        if att in data:
            ev[att] = data[att]

#     print(row[new_cols].dropna())
#     print(ev)
#     print()
    y_pred.append(inference.map_query(['ICU'], evidence=ev, show_progress=False)['ICU'])
In [18]:
from sklearn.metrics import precision_score, r2_score
from sklearn.metrics import confusion_matrix
confusion_matrix(y, y_pred)
Out[18]:
array([[135,  55],
       [ 74, 121]])