ANOVA-OLS Prediction of Surgical Volumes

Operating rooms (ORs) are some of the most valuable hospital assets, generating a large part of hospital revenue. For efficient utilization of ORs, accurate schedules of assigned block time and sequences of patient cases need to be made [1]. Statistical models have been developed using datasets to predict daily surgical volumes weeks in advance. The quest was motivated by the need to make real-time adjustments to staff capacity and reallocation of the OR block time based on predicted future demand.

operating room (OR)
Photo by Piron Guillaume on Unsplash
Photo by Piron Guillaume on Unsplash

Following previous studies [3,4], we focus on the VUMC dataset for evaluation of our statistical models. The dataset represents a 48-week surgery schedule for VUMC recorded from October 10, 2011 to September 14, 2012.

Our method consists of the ANOVA null-hypothesis test for the total number of surgeries to see if these variables change from day to day with 99% confidence. The null hypothesis H0 is the statement that the total number of surgeries does not depend upon the weekday (DOW). The alternative hypothesis states that the total number of surgeries does vary from day to day.  

Next, the Ordinary Least Squares (OLS) linear regression formula [3,4] is applied to our target variable Actual Surgery as a function of 28 independent variables, T-28 to T-1.

The OLS regression results are assessed using the following metrics [4]: (adjusted) R2, F-statistic, Log-Likelihood, AIC, BIC, std err, MSE, MAE, and RMSE.

Contents:

  1. Workflow
  2. Ipynb Script
    1. We are ready to build and deploy our regression model(s).
    2. Predict the number of surgeries:
    3. Predicting the number of surgeries
    4. Predicting the number of surgeries
  3. Summary
  4. References

Workflow

  • Import/install libraries
  • Read the input dataset
  • Exploratory Data Analysis (EDA)
  • ANOVA H0-H1 test
  • Build OLS regression model
  • Model performance QC
  • Report summary

Ipynb Script

Let’s set the working directory YOURPATH

os.chdir(‘YOURPATH’)

and import the libraries of interest

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
from sklearn import metrics
import warnings
warnings.filterwarnings(‘ignore’)

Let’s read the Excel dataset

df = pd.read_excel(‘Dataset.xlsx’)

and check the content

df.head()

Input dataset table

df.shape

(241, 19)

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 241 entries, 0 to 240
Data columns (total 19 columns):
 #   Column    Non-Null Count  Dtype         
---  ------    --------------  -----         
 0   SurgDate  241 non-null    datetime64[ns]
 1   DOW       241 non-null    object        
 2   T - 28    241 non-null    int64         
 3   T - 21    241 non-null    int64         
 4   T - 14    241 non-null    int64         
 5   T - 13    241 non-null    int64         
 6   T - 12    241 non-null    int64         
 7   T - 11    241 non-null    int64         
 8   T - 10    241 non-null    int64         
 9   T - 9     241 non-null    int64         
 10  T - 8     241 non-null    int64         
 11  T - 7     241 non-null    int64         
 12  T - 6     241 non-null    int64         
 13  T - 5     241 non-null    int64         
 14  T - 4     241 non-null    int64         
 15  T - 3     241 non-null    int64         
 16  T - 2     241 non-null    int64         
 17  T - 1     241 non-null    int64         
 18  Actual    241 non-null    int64         
dtypes: datetime64[ns](1), int64(17), object(1)
memory usage: 35.9+ KB

Let’s get the descriptive statistics info

df.describe()

Descriptive statistics input data table

Let’s calculate correlations

df.corr()

T – 28T – 21T – 14T – 13T – 12T – 11T – 10T – 9T – 8T – 7T – 6T – 5T – 4T – 3T – 2T – 1Actual
T – 281.0000000.8947000.7669810.7612580.7642720.7696800.7442810.7186070.6978910.6698650.6694210.6797110.6854680.6861280.6550220.6294320.608290
T – 210.8947001.0000000.8714270.8625060.8491200.8396690.8218750.8073510.7946390.7692790.7713110.7667650.7662300.7637450.7429560.7183640.702459
T – 140.7669810.8714271.0000000.9755930.9403740.9188440.9134200.9247740.9199290.9004520.8901080.8635360.8460240.8456960.8481120.8214780.800877
T – 130.7612580.8625060.9755931.0000000.9773370.9550260.9415540.9404120.9311220.9144500.9119550.8955540.8782670.8705650.8627050.8350400.812730
T – 120.7642720.8491200.9403740.9773371.0000000.9866180.9620740.9415330.9221580.9040640.9128070.9194130.9109580.8938990.8769550.8473870.818714
T – 110.7696800.8396690.9188440.9550260.9866181.0000000.9792890.9477640.9181420.8964700.9064880.9202570.9239380.9088630.8856740.8518780.819855
T – 100.7442810.8218750.9134200.9415540.9620740.9792891.0000000.9733220.9351920.9122040.9185980.9222470.9279820.9261970.9079660.8712000.842193
T – 90.7186070.8073510.9247740.9404120.9415330.9477640.9733221.0000000.9715320.9550610.9456780.9333640.9258260.9245280.9228740.8951390.872890
T – 80.6978910.7946390.9199290.9311220.9221580.9181420.9351920.9715321.0000000.9848290.9692360.9483350.9300650.9203500.9277080.9092330.887675
T – 70.6698650.7692790.9004520.9144500.9040640.8964700.9122040.9550610.9848291.0000000.9845420.9600000.9383920.9255030.9342840.9181240.895779
T – 60.6694210.7713110.8901080.9119550.9128070.9064880.9185980.9456780.9692360.9845421.0000000.9839810.9632280.9465640.9506490.9279540.898900
T – 50.6797110.7667650.8635360.8955540.9194130.9202570.9222470.9333640.9483350.9600000.9839811.0000000.9849110.9643170.9596920.9373310.902827
T – 40.6854680.7662300.8460240.8782670.9109580.9239380.9279820.9258260.9300650.9383920.9632280.9849111.0000000.9841580.9687850.9431320.906040
T – 30.6861280.7637450.8456960.8705650.8938990.9088630.9261970.9245280.9203500.9255030.9465640.9643170.9841581.0000000.9831170.9509280.913242
T – 20.6550220.7429560.8481120.8627050.8769550.8856740.9079660.9228740.9277080.9342840.9506490.9596920.9687850.9831171.0000000.9700630.936430
T – 10.6294320.7183640.8214780.8350400.8473870.8518780.8712000.8951390.9092330.9181240.9279540.9373310.9431320.9509280.9700631.0000000.964727
Actual0.6082900.7024590.8008770.8127300.8187140.8198550.8421930.8728900.8876750.8957790.8989000.9028270.9060400.9132420.9364300.9647271.000000

We can plot the correlation matrix as an image

f = plt.figure(figsize=(19, 15))
plt.matshow(df.corr(), fignum=f.number)
plt.xticks(range(df.select_dtypes([‘number’]).shape[1]), df.select_dtypes([‘number’]).columns, fontsize=14, rotation=45)
plt.yticks(range(df.select_dtypes([‘number’]).shape[1]), df.select_dtypes([‘number’]).columns, fontsize=14)
cb = plt.colorbar()
cb.ax.tick_params(labelsize=14)
plt.title(‘Correlation Matrix’, fontsize=16);
plt.savefig(‘corrmatrix.png’)

correlation matrix

or a lower triangular matrix with annotations

lower triangular correlation matrix with annotations
We can see that the surgery volume correlation value decreases as the gap from the surgery day increases.

Let’s look at the mean and std of the Actual data grouped by DOW

df.groupby(‘DOW’)[‘Actual’].mean(), df.groupby(‘DOW’)[‘Actual’].std()

(DOW
 Fri    105.612245
 Mon    116.255319
 Thu    124.083333
 Tue    119.081633
 Wed    117.041667
 Name: Actual, dtype: float64,
 DOW
 Fri    26.357175
 Mon    18.456138
 Thu    10.379672
 Tue    10.864385
 Wed    11.240047
 Name: Actual, dtype: float64)

Let’s look at the mean and std of the T-1 data grouped by DOW

df.groupby(‘DOW’)[‘T – 1’].mean(), df.groupby(‘DOW’)[‘T – 1’].std()

(DOW
 Fri     97.428571
 Mon    110.787234
 Thu    117.583333
 Tue    114.020408
 Wed    110.416667
 Name: T - 1, dtype: float64,
 DOW
 Fri    25.922159
 Mon    18.863279
 Thu    10.394011
 Tue    10.296621
 Wed    11.100764
 Name: T - 1, dtype: float64)

Let’s calculate the number of surgeries per weekday

df[‘DOW’].value_counts()

Tue    49
Fri    49
Wed    48
Thu    48
Mon    47
Name: DOW, dtype: int64

Let’s create the barplot Actual-DOW

df2 = df[[‘DOW’, ‘Actual’]]
sns.color_palette(“flare”, as_cmap=True)
ax = sns.barplot(x=’DOW’,y=’Actual’, data=df)
ax.set(ylim=(80, 130))
plt.savefig(‘barplotactualdow.png’)

The corresponding boxplot is as follows

sns.color_palette(“flare”, as_cmap=True)
ax=sns.boxplot(x=’DOW’,y=’Actual’, data=df)
ax.set(ylim=(80, 150))
plt.savefig(‘boxplotactualdow.png’)

boxplot Actual-DOW

We can also look at the violine plot

sns.color_palette(“flare”, as_cmap=True)
ax=sns.violinplot(x=’DOW’,y=’Actual’, data=df)
plt.savefig(‘violineplotactualdow.png’)

violine plot Actual-DOW

Let’s create the table new with 3 columns [‘Mean’, ‘Maximum’, ‘Standard Deviation’]

test=df.loc[1:242, ‘T – 28′:’T – 1’]

mean = test.mean()
maximum = test.max()
std = test.std()

a = pd.DataFrame(mean)
b = pd.DataFrame(maximum)
c = pd.DataFrame(std)
new = pd.concat([a,b,c], axis = 1)
new.columns = [‘Mean’, ‘Maximum’, ‘Standard Deviation’]
new

Three-column table mean, max and std

Let’s perform the OLS fitting while running the ANOVA H0-H1 test

import statsmodels.api as sm
from statsmodels.formula.api import ols

model = ols(‘Actual ~ DOW’, data=df).fit()
aov_table = sm.stats.anova_lm(model, typ=2)
aov_table

ANOVA test table

We reject the H0 hypothesis at the 99% confidence since p-value is less than 0.05.

Let’s perform multiple pairwise comparison of mean surgery volumes using the Tukey HSD test. The idea is to examine the difference between daily surgery volumes by taking various combinations of any two (randomly selected) weekdays

from statsmodels.stats.multicomp import pairwise_tukeyhsd
tukey = pairwise_tukeyhsd(endog=df[‘Actual’], groups=df[‘DOW’], alpha=0.05)
print(tukey)

 Multiple Comparison of Means - Tukey HSD, FWER=0.05 
=====================================================
group1 group2 meandiff p-adj   lower    upper  reject
-----------------------------------------------------
   Fri    Mon  10.6431  0.017   1.2798 20.0063   True
   Fri    Thu  18.4711    0.0   9.1577 27.7844   True
   Fri    Tue  13.4694 0.0008   4.2042 22.7346   True
   Fri    Wed  11.4294 0.0077   2.1161 20.7428   True
   Mon    Thu    7.828 0.1529  -1.5829 17.2389  False
   Mon    Tue   2.8263 0.9212   -6.537 12.1896  False
   Mon    Wed   0.7863 0.9994  -8.6246 10.1972  False
   Thu    Tue  -5.0017 0.5789 -14.3151  4.3117  False
   Thu    Wed  -7.0417 0.2376 -16.4029  2.3196  False
   Tue    Wed    -2.04 0.9747 -11.3533  7.2734  False
-----------------------------------------------------

This test confirms significant differences between various combinations of daily surgery volumes by considering any two (randomly selected) weekdays.

We are ready to build and deploy our regression model(s).

Let’s prepare the data by excluding the ouliers (cf. boxplot and violineplot)

df1 = df.drop(columns = [‘SurgDate’, ‘DOW’])

from scipy import stats
df1 = df1[(np.abs(stats.zscore(df1)) < 3).all(axis=1)]

Let’s begin with the T-1, T-2, and T-3 variables x being related to the target variable y as follows

x = df[[‘T – 3’, ‘T – 2’, ‘T – 1’]]
y = df[[‘Actual’]]

First, let’s try sklearn linear_model
from sklearn import linear_model
import statsmodels.api as sm
regr = linear_model.LinearRegression()
regr.fit(x, y)

print(‘Intercept: \n’, regr.intercept_)
print(‘Coefficients: \n’, regr.coef_)

Intercept: 
 [10.96140663]
Coefficients: 
 [[-0.14256711  0.15693554  0.94016588]]

Second, we invoke OLS statsmodels

model = sm.OLS(y, x).fit()
predictions = model.predict(x)

print_model = model.summary()
print(print_model)

OLS Regression Results                                
=======================================================================================
Dep. Variable:                 Actual   R-squared (uncentered):                   0.998
Model:                            OLS   Adj. R-squared (uncentered):              0.998
Method:                 Least Squares   F-statistic:                          4.535e+04
Date:                Mon, 27 Jun 2022   Prob (F-statistic):                        0.00
Time:                        11:39:33   Log-Likelihood:                         -725.88
No. Observations:                 241   AIC:                                      1458.
Df Residuals:                     238   BIC:                                      1468.
Df Model:                           3                                                  
Covariance Type:            nonrobust                                                  
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
T - 3         -0.1908      0.099     -1.926      0.055      -0.386       0.004
T - 2          0.1453      0.127      1.144      0.254      -0.105       0.395
T - 1          1.0908      0.069     15.891      0.000       0.956       1.226
==============================================================================
Omnibus:                        4.980   Durbin-Watson:                   1.916
Prob(Omnibus):                  0.083   Jarque-Bera (JB):                4.972
Skew:                           0.245   Prob(JB):                       0.0833
Kurtosis:                       3.506   Cond. No.                         89.7
==============================================================================

Notes:
[1] R² is computed without centering (uncentered) since the model does not contain a constant.
[2] Standard Errors assume that the covariance matrix of the errors is correctly specified.

We can also fit the simple linear regression model

from sklearn.linear_model import LinearRegression
regressorObject=LinearRegression()
regressorObject.fit(x,y)

Predict the number of surgeries:

predict = df1.loc[2:242, ‘T – 3′:’T – 1’]
y_pred_test_data=regressorObject.predict(predict)

Predicted = pd.DataFrame(y_pred_test_data, columns = [‘Predicted’])

result = pd.concat([df, Predicted], ignore_index=True, axis=1)
result.columns = [‘SurgDate’, ‘DOW’, ‘T – 28’, ‘T – 21’, ‘T – 14’, ‘T – 13’, ‘T – 12’, ‘T – 11′,’ T – 10′, ‘T – 9’,
‘T – 8’, ‘T – 7’, ‘T – 6’, ‘T – 5’, ‘T – 4’, ‘T – 3’, ‘T – 2’, ‘T – 1’, ‘Actual’, ‘Predicted’]
result[‘Predicted’] = round(result[‘Predicted’])

final = result.dropna()
final.tail(10)

predicted number of surgeries linear regression

Let’s calculate RMS

from sklearn.metrics import mean_squared_error
from math import sqrt
y_actual = final[‘Actual’]
y_predicted = final[‘Predicted’]
rms = sqrt(mean_squared_error(y_actual, y_predicted))
rms

20.653782302625718

Let’s calculate other performance metrics

y = final[‘Actual’]
yhat = final[‘Predicted’]
d = y – yhat
mse_f = np.mean(d2)

mae_f = np.mean(abs(d)) rmse_f = np.sqrt(mse_f) r2_f = 1-(sum(d2)/sum((y-np.mean(y))**2))

print(“Results by manual calculation:”)
print(“MAE:”,mae_f)
print(“MSE:”, mse_f)
print(“RMSE:”, rmse_f)
print(“R-Squared:”, r2_f)

Results by manual calculation:
MAE: 14.953191489361702
MSE: 426.5787234042553
RMSE: 20.653782302625718
R-Squared: -0.3528353839078937

Recall that the above model was applied to the three variables ‘T – 3′:’T – 1’.

Now let us consider 16 variables. We want to predict results for 3 days before the Surgery Date

x = df1[[‘T – 28’, ‘T – 21’, ‘T – 14’, ‘T – 13’, ‘T – 12’, ‘T – 11’, ‘T – 10’, ‘T – 9’, ‘T – 8’, ‘T – 7’,
‘T – 6’, ‘T – 5’, ‘T – 4’, ‘T – 3’, ‘T – 2’, ‘T – 1’]]
y = df1[[‘Actual’]]

by predicting results for 3 days before the Surgery Date.

Let’s re-apply our regression models

With sklearn linear_model
from sklearn import linear_model
import statsmodels.api as sm
regr = linear_model.LinearRegression()
regr.fit(x, y)

print(‘Intercept: \n’, regr.intercept_)
print(‘Coefficients: \n’, regr.coef_)

Intercept: 
 [14.84638197]
Coefficients: 
 [[-0.03590406  0.0856059  -0.10080439  0.07939623  0.08764874 -0.20750371
   0.03761113  0.10250478  0.00932406  0.12867575 -0.11420405 -0.03460241
   0.06443631 -0.15945052  0.12085577  0.87903786]]

With OLS statsmodels

model = sm.OLS(y, x).fit()
predictions = model.predict(x)

print_model = model.summary()
print(print_model)

OLS Regression Results                                
=======================================================================================
Dep. Variable:                 Actual   R-squared (uncentered):                   0.998
Model:                            OLS   Adj. R-squared (uncentered):              0.998
Method:                 Least Squares   F-statistic:                              8646.
Date:                Mon, 27 Jun 2022   Prob (F-statistic):                   4.06e-299
Time:                        11:58:15   Log-Likelihood:                         -705.05
No. Observations:                 237   AIC:                                      1442.
Df Residuals:                     221   BIC:                                      1498.
Df Model:                          16                                                  
Covariance Type:            nonrobust                                                  
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
T - 28        -0.0402      0.079     -0.507      0.612      -0.196       0.116
T - 21         0.0955      0.084      1.142      0.254      -0.069       0.260
T - 14        -0.1061      0.126     -0.845      0.399      -0.354       0.141
T - 13         0.1548      0.189      0.821      0.413      -0.217       0.526
T - 12        -0.0594      0.214     -0.278      0.781      -0.480       0.362
T - 11        -0.0900      0.210     -0.429      0.669      -0.504       0.324
T - 10        -0.0144      0.168     -0.086      0.932      -0.345       0.316
T - 9          0.1131      0.150      0.756      0.451      -0.182       0.408
T - 8         -0.0078      0.152     -0.052      0.959      -0.307       0.291
T - 7          0.2021      0.178      1.133      0.259      -0.149       0.554
T - 6         -0.1933      0.193     -1.002      0.317      -0.573       0.187
T - 5         -0.0897      0.182     -0.492      0.623      -0.448       0.269
T - 4          0.1104      0.183      0.605      0.546      -0.249       0.470
T - 3         -0.1945      0.159     -1.227      0.221      -0.507       0.118
T - 2          0.1490      0.138      1.083      0.280      -0.122       0.420
T - 1          1.0405      0.072     14.501      0.000       0.899       1.182
==============================================================================
Omnibus:                        6.221   Durbin-Watson:                   1.995
Prob(Omnibus):                  0.045   Jarque-Bera (JB):                7.642
Skew:                           0.204   Prob(JB):                       0.0219
Kurtosis:                       3.779   Cond. No.                         314.
==============================================================================

Notes:
[1] R² is computed without centering (uncentered) since the model does not contain a constant.
[2] Standard Errors assume that the covariance matrix of the errors is correctly specified.

Fitting Simple Linear regression data model
from sklearn.linear_model import LinearRegression
regressorObject=LinearRegression()
regressorObject.fit(x,y)

Predicting the number of surgeries

predict = df1.loc[2:242, ‘T – 28′:’T – 1’]
y_pred_test_data=regressorObject.predict(predict)

Predicted = pd.DataFrame(y_pred_test_data, columns = [‘Predicted’])

result2 = pd.concat([df, Predicted], ignore_index=True, axis=1)
result2.columns = [‘SurgDate’, ‘DOW’, ‘T – 28’, ‘T – 21’, ‘T – 14’, ‘T – 13’, ‘T – 12’, ‘T – 11′,’ T – 10′, ‘T – 9’,
‘T – 8’, ‘T – 7’, ‘T – 6’, ‘T – 5’, ‘T – 4’, ‘T – 3’, ‘T – 2’, ‘T – 1’, ‘Actual’, ‘Predicted’]
result2[‘Predicted’] = round(result2[‘Predicted’])

final2 = result2.dropna()

round(result[‘Actual’].mean()), round(result2[‘Predicted’].mean())

(116, 118)

We can see that the Average Daily Error of surgeries is ~2 Surgeries.

Let’s check RMS

from sklearn.metrics import mean_squared_error
from math import sqrt
y_actual = final2[‘Actual’]
y_predicted = final2[‘Predicted’]
rms = sqrt(mean_squared_error(y_actual, y_predicted))
rms

20.367475114829315

Let’s calculate other performance metrics

y = final2[‘Actual’]
yhat = final2[‘Predicted’]
d = y – yhat
mse_f = np.mean(d2) mae_f = np.mean(abs(d)) rmse_f = np.sqrt(mse_f) r2_f = 1-(sum(d2)/sum((y-np.mean(y))**2))

print(“Results by manual calculation:”)
print(“MAE:”,mae_f)
print(“MSE:”, mse_f)
print(“RMSE:”, rmse_f)
print(“R-Squared:”, r2_f)

Results by manual calculation:
MAE: 14.697872340425532
MSE: 414.83404255319147
RMSE: 20.367475114829315
R-Squared: -0.3155887540215563

Predicting results for 7 days before the surgery date.

Let’s set x and y

x = df1[[‘T – 28’, ‘T – 21’, ‘T – 14’, ‘T – 13’, ‘T – 12’, ‘T – 11’, ‘T – 10’, ‘T – 9’, ‘T – 8’]]
y = df1[[‘Actual’]]

Fitting Simple Linear regression data model
from sklearn.linear_model import LinearRegression
regressorObject=LinearRegression()
regressorObject.fit(x,y)

Predicting the number of surgeries

predict = df1.loc[2:242, ‘T – 28′:’T – 8’]
y_pred_test_data=regressorObject.predict(predict)

Predicted = pd.DataFrame(y_pred_test_data, columns = [‘Predicted’])

result3 = pd.concat([df, Predicted], ignore_index=True, axis=1)
result3.columns = [‘SurgDate’, ‘DOW’, ‘T – 28’, ‘T – 21’, ‘T – 14’, ‘T – 13’, ‘T – 12’, ‘T – 11′,’ T – 10′, ‘T – 9’,
‘T – 8’, ‘T – 7’, ‘T – 6’, ‘T – 5’, ‘T – 4’, ‘T – 3’, ‘T – 2’, ‘T – 1’, ‘Actual’, ‘Predicted’]
result3[‘Predicted’] = round(result3[‘Predicted’])

final3 = result3.dropna()

round(result[‘Actual’].mean()), round(final3[‘Predicted’].mean())

(116, 118)

We see that the Average Daily Error is ~2 Surgeries.

Let’s check the performance

y = final3[‘Actual’]
yhat = final3[‘Predicted’]
d = y – yhat
mse_f = np.mean(d2) mae_f = np.mean(abs(d)) rmse_f = np.sqrt(mse_f) r2_f = 1-(sum(d2)/sum((y-np.mean(y))**2))

print(“Results by manual calculation:”)
print(“MAE:”,mae_f)
print(“MSE:”, mse_f)
print(“RMSE:”, rmse_f)
print(“R-Squared:”, r2_f)

Results by manual calculation:
MAE: 13.565957446808511
MSE: 375.6085106382979
RMSE: 19.380622039508893
R-Squared: -0.19119040826349143

Let’s plot actual versus predicted values

plt.figure(figsize=[15,8])
plt.grid(True)
plt.plot(result[‘Actual’],label=’Actual’)
plt.plot(result[‘Predicted’],label=’Predicted’)

plt.ylim(80, 150)
plt.legend(loc=2)
plt.savefig(‘predictedactualdata.png’)

actual vs predicted values

And the % relative error is

plt.figure(figsize=[15,8])
plt.grid(True)
plt.plot(100*abs((result[‘Actual’]-result[‘Predicted’])/result[‘Actual’]))
plt.ylim([0, 40])
plt.savefig(‘predictrelerror.png’)

relative error %

Summary

Our input data have 4 outliers (11/25/2011, 12/23/2011, 12/26/2011, and 12/30/2011).

Our data analysis shows that Fridays/Thursdays have the lowest/highest number of surgeris.

The surgery volume correlation value between DOW and the actual Surgery Date (SD) decreases as the gap between DOW and SD increases.

The ANOVE test rejects our null hypothesis H0 with 99% confidence.

Our results are statistically significant since p<<0.05.

We have performed multiple pairwise comparison (Tukey HSD) test to confirm the acceptance of our H1 hypothesis.

Predicting surgery volumes for 7 days before the Surgery Date yields the best result, as shown below:

MetricBase Model3 Days Forecast7 Days Forecast
MAE14.9514.6913.56
MSE426.57414.83375.60
RMSE20.6520.3619.38
R2-0.35-0.31-0.19

This project supports earlier studies [1, 2] in that it underlines the importance of the implementation of automatic registration systems that integrate into the work processes in the OR to collect more and better data.

References

[1] Edelman et al, Front Med (Lausanne). 2017; 4: 85.

Published online 2017 Jun 19. doi: 10.3389/fmed.2017.00085

[2] Eun et al, Decision Sciences, 07 August 2020

[3] Rashi Desai, 2021, Vanderbilt University Medical Center: Effective Surgery Schedule. Github Repository.

[4] Cem ÖZÇELİK, 2022, DATA SCIENCE PROJECT: PREDICTING THE AMOUNT OF SURGERY, Published in MLearning.ai.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: