# To run model
import PHC
from reproduction_helpers import process_results
# To import results and produce figures
import xlrd
import pandas as pd
import os
import matplotlib.pyplot as plt
import numpy as np
# To speed up run time
from multiprocessing import Pool
# Additional package to record runtime of this notebook
import time
= time.time() start
Reproducing in-text result 2
This notebook aims to reproduce in-text result 2 from Shoaib M, Ramamohan V. Simulation modeling and analysis of primary health center operations. SIMULATION 98(3):183-208. (2022). https://doi.org/10.1177/00375497211030931.
In-text result 2:
“To address this, we experimented with letting the staff nurse (whose utilisation is approximately 32%) take over the administrative work. This led to a 12% drop in the utilisation level, which implied that the doctor’s utilisation still exceeded 100%. Implementing this measure resulted in increasing the staff nurse utilisation to nearly 40%.”
Parameters
This result starts with the doctor utilisation from Figure 2A which is over 100% when patient load is 170 (IAT 3) and appointment times are 5 minutes (mean 5, SD 1, boundary 2).
The variant introduced is to give all administrative work to the staff nurse.
Set up
# Paths to save image files to
= '../outputs'
output_folder = os.path.join(output_folder, 'intext2.csv') save_path
Run model
# Parameters used in both models
= {
base_model 'OPD_iat': 3,
'rep_file': 'arr170',
'mean': 5,
'sd': 1,
'consult_boundary_1': 2,
'consult_boundary_2': 2
}
# Model variants
= [
variants
{'admin_doc_to_staff': False,
'rep_file': 'in2_admin_doctor.xls'
},
{'admin_doc_to_staff': True,
'rep_file': 'in2_admin_nurse.xls'
}, ]
# Combine dictionaries
= []
dict_list for var in variants:
**base_model, **var})
dict_list.append({
# Append 's_' to all items
for i, d in enumerate(dict_list):
= {f's_{k}': v for k, v in d.items()}
dict_list[i]
# View dictionaries
dict_list
[{'s_OPD_iat': 3,
's_rep_file': 'in2_admin_doctor.xls',
's_mean': 5,
's_sd': 1,
's_consult_boundary_1': 2,
's_consult_boundary_2': 2,
's_admin_doc_to_staff': False},
{'s_OPD_iat': 3,
's_rep_file': 'in2_admin_nurse.xls',
's_mean': 5,
's_sd': 1,
's_consult_boundary_1': 2,
's_consult_boundary_2': 2,
's_admin_doc_to_staff': True}]
# Wrapper function to allow input of dictionary with pool
def wrapper(d):
return PHC.main(**d)
# Create a process pool that uses all CPUs
with Pool() as pool:
# Run PHC.main() using each of inputs from config
map(wrapper, dict_list) pool.
No of replications done No of replications done 00
No of replications done 1
No of replications done 1
No of replications done 2
No of replications done 2
No of replications done 3
No of replications done 3
No of replications done 4
No of replications done 4
No of replications done 5
No of replications done 5
No of replications done 6
No of replications done 6
No of replications done 7
No of replications done 7
No of replications done 8
No of replications done 8
No of replications done 9
No of replications done 9
Process results
# Process results
= process_results([i['s_rep_file'] for i in dict_list], xls=True) data
def get_utilisation(index_name, new_name):
'''
Creates dataframe with columns for utilisation (for a given row) before and
after admin change and the change in utilisation..
Parameters:
-----------
index_name : string
Name of row with utilisation dat
new_name : string
To rename the utilisation row (e.g. doc occ -> doctor utilisation)
Returns:
--------
util : pandas DataFrame
Dataframe with three columns for utilisation before and after admin,
and change in utilisation.
'''
# Get utilisation
= round(pd.DataFrame(data.loc[index_name]).T, 3)
util
# Find change
'Change'] = util['in2_admin_nurse'] - util['in2_admin_doctor']
util[
# Rename index
= util.rename_axis('Output')
util # Rename row
= util.rename({index_name: new_name})
util # Rename columns for clarity for readers
= util.rename({
util 'in2_admin_doctor': 'Original utilisation',
'in2_admin_nurse': (
'Utilisation if admin is assigned to the staff nurse')
=1)
}, axis
return util
# Get results for doctor utilisation and staff nurse utilisation
= pd.concat([
util 'doc occ', 'Doctor utilisation'),
get_utilisation('staff nurse occ', 'Staff nurse utilisation')])
get_utilisation(
# Display results
display(util)
# Save results
=True) util.to_csv(save_path, index
Original utilisation | Utilisation if admin is assigned to the staff nurse | Change | |
---|---|---|---|
Output | |||
Doctor utilisation | 1.141 | 1.023 | -0.118 |
Staff nurse utilisation | 0.326 | 0.404 | 0.078 |
Run time
# Find run time in seconds
= time.time()
end = round(end-start)
runtime
# Display converted to minutes and seconds
print(f'Notebook run time: {runtime//60}m {runtime%60}s')
Notebook run time: 2m 29s