Patient Characteristics and Readmission Modeling

Patient Characteristics and Readmission Modeling

Introduction

Hospital X seeks our expertise in comprehensively analyzing a decade’s worth of data on patient readmissions following discharge. The medical staff is seeking our assistance in determining whether initial diagnoses, number of procedures, or other factors can help better predict the probability of readmission. They hope to use the findings to target follow-up calls and attention to patients who are more likely to be readmitted.

Objectives

The main objective of this report is to explore patient characteristics and readmissions. It specifically aims to:

  1. Describe the overall and by age characteristics of the patients.
  2. Investigate and model the patient readmissions by their representing features.
  3. Identify patient groups with the best readmission rates.

Data Used

The hospital information used in this report is part of the clinical care at 130 US hospitals and integrated delivery networks. Below is a list of variables and their descriptions:

vars-desc

Acknowledgments: Beata Strack, Jonathan P. DeShazo, Chris Gennings, Juan L. Olmo, Sebastian Ventura, Krzysztof J. Cios, and John N. Clore, “Impact of HbA1c Measurement on Hospital Readmission Rates: Analysis of 70,000 Clinical Database Patient Records,” BioMed Research International, vol. 2014, Article ID 781670, 11 pages, 2014.

# ---------- Packages & Datasets

# Load pre-installed, required packages
suppressPackageStartupMessages(library(tidyverse)) 
suppressPackageStartupMessages(library(dplyr)) 
suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(scales))

# Install and load the 'ggfun' package
# For round rectangle borders and backgrounds in ggplots
suppressWarnings(suppressMessages(install.packages("ggfun", verbose=TRUE, quiet=TRUE)))
suppressPackageStartupMessages(library(ggfun))

# Install and load the 'ggchicklet' package
# For bar charts with rounded corners
suppressWarnings(suppressMessages(remotes::install_github("hrbrmstr/ggchicklet", auth_token = "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")))
suppressPackageStartupMessages(library("ggchicklet"))

# Install and load the 'ggthemes' package
# For using the look of a plot theme
suppressWarnings(suppressMessages(install.packages("ggthemes")))
suppressPackageStartupMessages(library(ggthemes))

# Install and load the 'patchwork' package
# For combining ggplots into the same graphic					   
suppressWarnings(suppressMessages(install.packages("patchwork", verbose=TRUE, quiet=TRUE))) 
suppressPackageStartupMessages(library(patchwork))

# Install and load the "mlbench" package
#									   
#suppressWarnings(suppressMessages(install.packages("mlbench")))
#suppressPackageStartupMessages(library(mlbench))

# Install and load the "ggpubr" package
# For boxplots
suppressWarnings(suppressMessages(install.packages("ggpubr")))
suppressPackageStartupMessages(library("ggpubr"))
									   
# Read 'readmissions' dataset
readmissions <- readr::read_csv('data/hospital_readmissions.csv', show_col_types = FALSE) %>%
	mutate_if(is.character,as.factor) %>%
	mutate_all(~ if_else(.x == "Missing", NA,.x))

#is.na(readmissions)
#colSums(is.na(readmissions))
#which(colSums(is.na(readmissions))>0)
#names(which(colSums(is.na(readmissions))>0))
#missmap(readmissions, col=c("blue", "red"), legend=FALSE)

#summary(readmissions)
#par(mfrow=c(1,6))
#for(i in 1:17) {
#    boxplot(readmissions[,i], main=names(readmissions)[i])
#}
The following package(s) will be installed:
- ggthemes [5.1.0]
These packages will be installed into "~/renv/library/linux-ubuntu-jammy/R-4.4/x86_64-pc-linux-gnu".

# Installing packages --------------------------------------------------------
- Installing ggthemes ...                       OK [linked from cache]
Successfully installed 1 package in 6.4 milliseconds.
The following package(s) will be installed:
- ggpubr [0.6.0]
These packages will be installed into "~/renv/library/linux-ubuntu-jammy/R-4.4/x86_64-pc-linux-gnu".

# Installing packages --------------------------------------------------------
- Installing ggpubr ...                         OK [linked from cache]
Successfully installed 1 package in 6.3 milliseconds.
# ----- For link's image thumbnail

# Install and load the 'png' package
# For superimposing PNG images in a ggplot								   
suppressWarnings(suppressMessages(install.packages("png", verbose=TRUE, quiet=TRUE)))       
suppressPackageStartupMessages(library(png))  

# Create a data
data <- data.frame(x = 1:3,
                   y = 1:3)

# Read the PNG file
my_image <- readPNG("documentation/cover_Fig10_diag_stacked_bar_plot.png", native = TRUE)

# Create a plot and combine with the image
ggplot(data, aes(x, y)) +
	geom_point() +
	theme_minimal() +
	theme(axis.title = element_blank(),
          axis.text = element_blank(),
          axis.line = element_blank(),
          axis.ticks = element_blank()) +
	inset_element(p = my_image,
                  left = -0.52,
                  bottom = -0.03,
                  right = 1.52,
                  top = 1.02)

png

Results and Discussion

Patient Characteristics

The following information describe the characteristics of the sample composing of 25,000 patients admitted to the hospital after being discharged.

Overall

Numerical

Age: The grouped mean and median ages are approximately 68 and 69, respectively, with a standard deviation of ~13, indicating that the hospital primarily admitted elderly patients. As shown in Figure 1, the distribution of patients across age groups is approximately symmetric at the mean.

# Frequency Distribution Table (FDT) for Age
age_fdt <- readmissions %>%
	select(age) %>%
	group_by(age) %>%
	count() %>%
	mutate(class_interval = paste(as.numeric(unlist(regmatches(age, gregexpr("[[:digit:]]+", age)))), collapse = "-"),
           class_mark = mean(as.numeric(unlist(regmatches(age, gregexpr("[[:digit:]]+", age)))))) %>%
	ungroup() %>%
	mutate(cum_freq = cumsum(n),
           n_times_cm = n*class_mark) %>%
	select(age, class_interval, everything())

# Create GroupedMedian() function to calculate the median of grouped data	
# Reference: http://stackoverflow.com/a/18931054/1270695
GroupedMedian <- function(frequencies, intervals, sep = NULL, trim = NULL) {
  # If "sep" is specified, the function will try to create the 
  #   required "intervals" matrix. "trim" removes any unwanted 
  #   characters before attempting to convert the ranges to numeric.
  if (!is.null(sep)) {
    if (is.null(trim)) pattern <- ""
    else if (trim == "cut") pattern <- "\\[|\\]|\\(|\\)"
    else pattern <- trim
    intervals <- sapply(strsplit(gsub(pattern, "", intervals), sep), as.numeric)
  }

  Midpoints <- rowMeans(intervals)
  cf <- cumsum(frequencies)
  Midrow <- findInterval(max(cf)/2, cf) + 1
  L <- intervals[1, Midrow]      # lower class boundary of median class
  h <- diff(intervals[, Midrow]) # size of median class
  f <- frequencies[Midrow]       # frequency of median class
  cf2 <- cf[Midrow - 1]          # cumulative frequency class before median class
  n_2 <- max(cf)/2               # total observations divided by 2

  unname(L + (n_2 - cf2)/f * h)
}

# Grouped Mean, Median, and Sample SD
grouped_age_stats <- age_fdt %>% 
 	summarize(Variable = "Age group",
			  "Mean" = sum(n_times_cm)/sum(n),
              "Std. Dev." = sqrt(sum(n*(Mean-class_mark)^2)/(sum(n))),
			  "Med." = GroupedMedian(frequencies = age_fdt$n, intervals = age_fdt$class_interval, sep = "-")
			 )

grouped_age_stats

# Bar plot
age_bar_plot <- ggplot(age_fdt, aes(group=1)) + 
	geom_chicklet(aes(x = age,
                      y = n,
					  group=1), 
                  color="white",
                  fill="#6C8CBF",
                  radius = grid::unit(1, "mm"), position="stack") +
    
	# Plot mean and median lines
	geom_vline(xintercept=3.344, color="red", linewidth=0.6) +
 
	ggtitle("Fig. 1: Bar Graph of the Patients' Age Groups\n") +
	labs(x="\nAge group", y="Number of patients\n") +
	scale_y_continuous(expand = c(0.01, 0), limits = c(0,7000),
                      breaks = seq(0, 7000, by=1000)) +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          axis.ticks = element_blank()
         ) +
	annotate("text", x=2.7, y=6500, 
			 label=paste("Mean = ",sum(age_fdt$n_times_cm)/sum(age_fdt$n)),
			 color="red",
			 size=3.5)
A tibble: 1 × 4
VariableMeanStd. Dev.Med.
<chr><dbl><dbl><dbl>
Age group68.441213.1560769.3286

Time in hospital: The mean and median lengths of stay in the hospital are 4.4533 and 4, respectively, with a standard deviation of ~3. Figure 2 shows a positively skewed distribution for this patient feature.

# Summary statistics for numerical variables
sum_stats <- data.frame(
    Variable = readmissions %>%
		select_if(is.numeric) %>%
		colnames) %>%
	bind_cols(as.data.frame(t(readmissions %>%
                              summarise_if(is.numeric, list(mean)) %>%
                              bind_rows(readmissions %>%
                                        	summarise_if(is.numeric, list(sd)), 
                                        readmissions %>%
                                        	summarise_if(is.numeric, list(min)),
                                        readmissions %>%
                                        	summarise_if(is.numeric, list(median)),
                                        readmissions %>%
                                        	summarise_if(is.numeric, list(max)))
                             )) %>%
              rename(Mean = V1,
                     `Std. Dev.` = V2,
                     `Min.` = V3,
                     `Median` = V4,
                     `Max.` = V5))

rownames(sum_stats) <- 1: nrow(sum_stats)
sum_stats

# time in hospital
time_in_hospital_dst_plot <- ggplot(readmissions, aes(x = time_in_hospital)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=1) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(time_in_hospital)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(time_in_hospital)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 2: Distribution of the Time Length in Hospital\n") +
	labs(x="\nNumber of days (from 1 to 14)", y="Density\n") +
	scale_x_continuous(expand = c(0.01, 0), 
                       breaks = seq(0, 14, by=2)) +
	scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0,0.20),
                       breaks = seq(0,0.20, by=0.025)) +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=mean(readmissions$time_in_hospital)+1.45, y=(0.200+0.175)/2, 
			 label=paste("Mean = ",round(mean(readmissions$time_in_hospital),4)),
			 color="red",
			 size=3.5)
A data.frame: 7 × 6
VariableMeanStd. Dev.Min.MedianMax.
<chr><dbl><dbl><dbl><dbl><dbl>
1time_in_hospital 4.45332 3.00146991 4 14
2n_lab_procedures43.2407619.8186202144113
3n_procedures 1.35236 1.71517930 1 6
4n_medications16.25240 8.0605318115 79
5n_outpatient 0.36640 1.19547820 0 33
6n_inpatient 0.61596 1.17795110 0 15
7n_emergency 0.18660 0.88587350 0 64

Number of procedures: The mean and median number of medical procedures performed during the hospital stay are 1.3524 and 1, with a standard deviation of 1.7152, respectively, whereas the mean and median numbers of laboratory procedures performed are 43.2408 and 44, respectively, with a standard deviation of 19.8186. This implies that throughout their hospitalization, patients underwent laboratory procedures more frequently than medical procedures.

Based on Figures 3 and 4, the two types of procedures exhibit dissimilar distributional characteristics, with medical procedures demonstrating positive skewness, and laboratory procedures showing slight symmetry.

# Number of Procedures
n_procedures_hs_dst_plot <- ggplot(readmissions, aes(x = n_procedures)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=0.5
                  ) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(n_procedures)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(n_procedures)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 3: Distribution of the Number of Medical Procedures\n") +
	labs(x="\nNumber of procedures performed during the hospital stay", y="Density\n") +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=mean(readmissions$n_procedures)+0.72, y=0.7, 
			 label=paste("Mean = ",round(mean(readmissions$n_procedures),4)),
			 color="red",
			 size=3.5)

# Number of Lab Procedures
n_lab_procedures_hs_dst_plot <- ggplot(readmissions, aes(x = n_lab_procedures)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=3
                  ) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(n_lab_procedures)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(n_lab_procedures)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 4: Distribution of the Number of Laboratory Procedures\n") +
	labs(x="\nNumber of lab procedures performed during the hospital stay", y="Density\n") +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=mean(readmissions$n_lab_procedures)+14, y=0.025, 
			 label=paste("Mean = ",round(mean(readmissions$n_lab_procedures),4)),
			 color="red",
			 size=3.5)

#ggarrange(n_procedures_hs_dst_plot, n_lab_procedures_hs_dst_plot, 
#          ncol = 1, nrow = 2)

Number of medications: The mean and median numbers of medications administered during the hospital stay are 16.2524 and 15, with a standard deviation of 8.0605, as well as a slightly skewed distribution to the right.

# Number of Procedures
n_medications_hs_dst_plot <- ggplot(readmissions, aes(x = n_medications)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=1
                  ) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(n_medications)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(n_medications)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 5: Distribution of the Number of Medications\n") +
	labs(x="\nNumber of medications administered during the hospital stay", y="Density\n") +
	scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0,0.065),
                       breaks = seq(0,0.065, by=0.01)) +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=mean(readmissions$n_medications)+9, y=0.065, 
			 label=paste("Mean = ",round(mean(readmissions$n_medications),4)),
			 color="red",
			 size=3.5)

Number of visits: The mean numbers of outpatient, inpatient, and emergency room visits in the year preceding a hospital stay are 0.3664, 0.616, and 0.1866, with medians of 0 for all types, and standard deviations of 1.1955, 1.178, and 0.8859, respectively. The numbers of visits for all types are positively skewed, indicating that visitation is not much frequent among patients a year prior to their hospitalization.

# Outpatient
n_outpatient_hs_dst_plot <- ggplot(readmissions, aes(x = n_outpatient)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=1
                  ) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(n_outpatient)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(n_outpatient)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 6: Distribution of the Number of Outpatient Visits\n") +
	labs(x="\nNumber of outpatient visits in the year before a hospital stay", y="Density\n") +
	scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0,1),
                       breaks = seq(0,1, by=0.2)) +
	scale_x_continuous(expand = c(0.01, 0),
                       #limits = c(0,75),
                       breaks = seq(0,35, by=5)) +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=3.6, y=0.97, 
			 label=paste("Mean = ",round(mean(readmissions$n_outpatient),4)),
			 color="red",
			 size=3.5)

# Inpatient
n_inpatient_procedures_hs_dst_plot <- ggplot(readmissions, aes(x = n_inpatient)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=1
                  ) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(n_inpatient)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(n_inpatient)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 7: Distribution of the Number of Inpatient Visits\n") +
	labs(x="\nNumber of inpatient visits in the year before the hospital stay", y="Density\n") +
	scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0,1),
                       breaks = seq(0,1, by=0.2)) +
	scale_x_continuous(expand = c(0.01, 0),
                       #limits = c(0,75),
                       breaks = seq(0,18, by=3)) +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=2, y=0.97, 
			 label=paste("Mean = ",round(mean(readmissions$n_inpatient),4)),
			 color="red",
			 size=3.5)

# Emergency
n_emergency_procedures_hs_dst_plot <- ggplot(readmissions, aes(x = n_emergency)) + 
	geom_histogram(aes(y=after_stat(density)),
                   colour="white",
                   fill="#5AA7A7",
                   binwidth=1
                   ) +
	geom_density(alpha=0.2,
                 fill="#FF6666") +

	# Plot mean and median lines
	geom_vline(aes(xintercept = mean(n_emergency)), col="red", linewidth=0.6) +
	#geom_vline(aes(xintercept = median(n_emergency)), col="blue", linewidth=0.6) +
	
	ggtitle("Fig. 8: Distribution of the Number of Emergency Room Visits\n") +
	labs(x="\nNumber of visits to the emergency room in the year before the hospital stay", y="Density\n") +
	scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0,1),
                       breaks = seq(0,1, by=0.2)) +
	scale_x_continuous(expand = c(0.01, 0),
                       #limits = c(0,75),
                       breaks = seq(0,75, by=10)) +
	theme_economist() + 
	scale_color_economist() +
	theme(plot.title = element_text(size= 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3)
         ) +
	annotate("text", x=6.7, y=0.97, 
			 label=paste("Mean = ",round(mean(readmissions$n_emergency),4)),
			 color="red",
			 size=3.5)

#ggarrange(n_outpatient_hs_dst_plot, 
#          n_inpatient_procedures_hs_dst_plot,
#          n_emergency_procedures_hs_dst_plot, 
#          ncol = 1, nrow = 3)

Categorical

Medical Specialty: Of the 12,618 (50.47%) patients with a recorded admitting physician, 3,565 had an admitting physician whose specialty was Internal Medicine.

# Frequency Distribution Table (FDT) for the Specialty of the Admitting Physician
medical_specialty_fdt <- readmissions %>%
	select(medical_specialty) %>%
	group_by(medical_specialty) %>%
	count() %>%
	ungroup() %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>%
	arrange(desc(n))

# Age
medical_specialty_bar_plot <- ggplot(medical_specialty_fdt %>% 
										filter(!is.na(medical_specialty))) + 
	geom_chicklet(aes(x = fct_reorder(medical_specialty,n),
                      y = n), 
                  fill=c("#6C8CBF"),
                  color="white",
                  radius = grid::unit(1, "mm"), position="stack",
				  na.rm = TRUE) +
	coord_flip() +
	ggtitle("Fig. 9: Bar Graph of the Specialty of Patients' Admitting Physician \n") +
	labs(y="\nNumber of patients", x="Specialty of the admitting physician\n") +
	theme_economist() + 
	scale_color_economist() + 
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          axis.ticks = element_blank(),
		  axis.text.y = element_text(size=10),
          legend.title = element_text(face="bold",
                                      size = 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 12),
          legend.box.margin = margin(t=0, b=0, l=-95, unit='pt'))  +
	#scale_y_continuous(expand = c(0.01, 0),
    #                   limits = c(0, 13000),
    #                   breaks = seq(0, 13000, by=2000)) +
	scale_x_discrete(expand = c(0.11, 0),
					 labels = rev(c("Internal\nMedicine",
								"Other",
								"Emergency/\nTrauma",
								"Family/\nGeneral\nPractice",
							    "Cardiology",
							    "Surgery"))
					 )

Diagnoses: Most of the circulatory diagnoses or 7,824 (31.30%) were identified as primary, whereas most of the patients who had a diagnosis other than circulatory, diabetes, digestive, injury, musculoskeletal, or respiratory received it as a secondary (9,056 or 36.22%) and additional secondary (9,107 or 36.43%).

# Table for the diagnoses
diag_tbl <- readmissions %>% 
	select(diag_1, diag_2, diag_3) %>%
	pivot_longer(cols = c(1:3), 
                 names_to = "diag_type",
                 values_to = "diag") %>%
	group_by(diag_type, diag) %>%
	summarize(n=n(), .groups="keep") %>%
	group_by(diag_type) %>%
	mutate(perc=label_percent(accuracy = 0.01)(n/sum(n))) %>%
	arrange(diag_type, desc(n)) %>%
	ungroup()


# Install and load the 'rwantshue' package
# For generating random color scheme
suppressWarnings(suppressMessages(install.packages("remotes")))
suppressWarnings(suppressMessages(remotes::install_github("hoesler/rwantshue", auth_token = "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")))
suppressPackageStartupMessages(library(rwantshue))

# Colorize the Physician's Specialty
color_scheme1 <- iwanthue(seed=1234, force_init=TRUE)
diag_colors <- color_scheme1$hex(length(levels(factor(diag_tbl$diag))))

#convert diagnostic type to factor and specify level order
diag_tbl$diag_type <- factor(diag_tbl$diag_type, levels=c('diag_3', 'diag_2', 'diag_1'))

diag_stacked_bar_plot <- ggplot(diag_tbl %>% filter(!is.na(diag))) + 
	geom_chicklet(aes(x = diag_type, y = n,
                      fill = fct_reorder(diag, n)),
                  color="white",
                  alpha=0.95,
                  radius = grid::unit(0.75, "mm"),
                  position="dodge") +
	coord_flip() +	
    #scale_x_discrete(labels = c("Additional Secondary", "Secondary", "Primary")) + 
	ggtitle("Fig. 10: Stacked Bar Graph of the Patients' Diagnoses\n") +
	labs(x="Diagnosis Type\n", y="\nNumber of patients", fill="Diagnosis: ") +
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=3,
                               reverse = TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          axis.ticks = element_blank(),
		  axis.text.y = element_text(size=10),
          legend.title = element_text(face="bold",
                                      size = 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 12),
          legend.box.margin = margin(t=0, b=0, l=-135, unit='pt')) +
	scale_fill_manual(values = diag_colors#,
					  #labels = rev(c("Missing",
					#			"Circulatory",
					#				 "Other",
					#			"Diabetes",
					#		    "Respiratory",
					#		    "Digestive",
					#			"Injury",
					#			"Musculoskeletal"))
					 ) +
	scale_y_continuous(expand = c(0.01, 0),
		               limits = c(0, 10200),
                       breaks = seq(0, 10200, by=2000)) +
	scale_x_discrete(expand = c(0.275, 0),
                    labels = c("Additional\nSecondary", "Secondary", "Primary")) 
The following package(s) will be installed:
- remotes [2.5.0]
These packages will be installed into "~/renv/library/linux-ubuntu-jammy/R-4.4/x86_64-pc-linux-gnu".

# Installing packages --------------------------------------------------------
- Installing remotes ...                        OK [linked from cache]
Successfully installed 1 package in 6.1 milliseconds.
curl     (5.2.1  -> 5.2.3   ) [CRAN]
jsonlite (1.8.8  -> 1.8.9   ) [CRAN]
Rcpp     (1.0.12 -> 1.0.13-1) [CRAN]
V8       (4.4.2  -> 6.0.0   ) [CRAN]
── R CMD build ─────────────────────────────────────────────────────────────────
* checking for file ‘/tmp/Rtmpvo1Xrr/remotes193d3d1cdf74/hoesler-rwantshue-07a58c7/DESCRIPTION’ ... OK
* preparing ‘rwantshue’:
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
Omitted ‘LazyData’ from DESCRIPTION
* building ‘rwantshue_0.0.3.tar.gz’

Prediabetes test results: A total of 20,938 (83.75%) had not performed an A1C test, while 23,625 (94.50%) had not performed a glucose test. For those who had performed, however, a high result was seen more than a normal one for A1C tests and almost equal number in high and normal results for glucose test.

# Table for Prediabetes tests
diab_test_tbl <- readmissions %>% 
	select(glucose_test, A1Ctest) %>%
	rename(A1C = A1Ctest, 
           Glucose = glucose_test) %>%
	pivot_longer(cols = c(1:2), 
                 names_to = "prediab_test",
                 values_to = "result") %>%
	group_by(prediab_test, result) %>%
	summarize(n=n(), .groups="keep") %>%
	group_by(prediab_test) %>%
	mutate(perc=label_percent(accuracy = 0.01)(n/sum(n))) %>%
	arrange(prediab_test, desc(n)) %>%
	ungroup()

#convert test result type to factor and specify level order
diab_test_tbl$result <- factor(diab_test_tbl$result, levels=c("no",'normal','high'))

diab_test_stacked_bar_plot <- ggplot(diab_test_tbl) + 
	geom_chicklet(aes(x = fct_reorder(prediab_test, n), y = n,
                      fill = result),
                  color="white",
                  alpha=0.95,
                  radius = grid::unit(0.75, "mm"),
                  position="dodge") +
	coord_flip() +	
	scale_fill_manual(values = c("#838484", "#8BD69D", "#BD3E38"),
                      labels = c("Not Performed", "Normal", "High")
                     ) + 
	ggtitle("Fig. 11: Stacked Bar Graph of the Patients' Prediabetes Test Results\n") +
	labs(x="Prediabetes test\n", y="\nNumber of patients", fill="Test Result:  ") +
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=3,
                               reverse = TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),
		  axis.text.y = element_text(size=10),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 12),
          legend.box.margin = margin(t=0, b=0, l=-200, unit='pt')) +
	scale_y_continuous(expand = c(0.01, 0),
		               limits = c(0, 25000),
                       breaks = seq(0, 24000, by=4000)) +
	scale_x_discrete(expand = c(0.5, 0))

Diabetes medication: Among all the patients, 19,228 (76.91%) had been prescribed a diabetes medication, while 13,497 (53.99%) had not changed diabetes medication.

# Table for change
diab_ques_tbl <- readmissions %>% 
	select(change, diabetes_med) %>%
	rename("Was there a  \nchange in the \ndiabetes \nmedication?" = change, 
           "Was there a  \nprescribed \ndiabetes \nmedication?"= diabetes_med) %>%
	pivot_longer(cols = c(1:2), 
                 names_to = "diab_ques",
                 values_to = "response") %>%
	group_by(diab_ques, response) %>%
	summarize(n=n(), .groups="keep") %>%
	group_by(diab_ques) %>%
	mutate(perc=label_percent(accuracy = 0.01)(n/sum(n))) %>%
	arrange(diab_ques, desc(n)) %>%
	ungroup()

diab_ques_stacked_bar_plot <- ggplot(diab_ques_tbl) + 
	geom_chicklet(aes(x = fct_reorder(diab_ques, n), y = n,
                      fill = fct_reorder(response, n)),
                  color="white",
                  alpha=0.95,
                  radius = grid::unit(0.75, "mm"),
                  position="stack") +
	coord_flip() +	
    scale_fill_manual(values = c("#EE6C4D", "#98C1D9"),
                      labels = c("No", "Yes")
                     ) +
	ggtitle("Fig. 12: Stacked Bar Graph of the Patient's Response to Questions Related to\n             Diabetes Medication\n") +
	labs(x="Question\n", y="\nNumber of patients", fill="Response:  ") +
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=2,
                               reverse = TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),
		  axis.text.y = element_text(size=9.5),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 10),
          legend.box.margin = margin(t=0, b=0, l=-290, unit='pt')) +
	scale_y_continuous(expand = c(0.01, 0),
		               limits = c(),
                       breaks = seq(0, 25000, by=3000)) +
	scale_x_discrete(expand = c(0.5, 0))

diab_ques_tbl
A tibble: 4 × 4
diab_quesresponsenperc
<chr><fct><int><chr>
Was there a change in the diabetes medication?no1349753.99%
Was there a change in the diabetes medication?yes1150346.01%
Was there a prescribed diabetes medication?yes1922876.91%
Was there a prescribed diabetes medication?no 577223.09%

# Table for change in diabetes medication
change_tbl <- readmissions %>%
  count(change, sort = TRUE) %>%
	mutate(proportion = n/sum(n),
           #Attribute = "change in the diabetes medication",
           Percentage = label_percent(accuracy=0.01)(proportion),
           lab.ypos = cumsum(proportion) - 0.6*proportion)

# Create a pie chart
change_pie_chart <- ggplot(change_tbl, aes(x = "", y = proportion, fill = change)) +
    geom_bar(width=1,
             stat = "identity",
             color = "white",
             linewidth=0.4) +
    coord_polar("y", start = 0, direction = -1) +
    geom_text(aes(y = lab.ypos, 
                  label = paste(label_percent(accuracy=0.01)(proportion),
                                "\n (", prettyNum(n,
                                                  big.mark=","),")",
                                sep="")), color = "grey5",  size = 5) +
    scale_fill_manual(values = c("#EE6C4D", "#98C1D9"),
                      labels = c("No", "Yes")
                     ) +
	ggtitle("Fig. 13: Pie Chart of Patient Distribution in Terms of the Change \nin Diabetes Medication") +
	labs(x="", y="",
         fill="Was there a change in the patient's diabetes medication?") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size=10),
          legend.title = element_text(face="bold",
                                      size = 11),
          axis.title = element_blank(),
          axis.text = element_blank(),
          axis.line = element_blank(),
          axis.ticks = element_blank(),
          panel.grid.minor = element_blank(),
		  panel.grid.major = element_blank(),
          plot.background = element_rect(fill = "#D5E4EB"),
          plot.title = element_text(vjust=7,
                                    hjust=0.5,
                                    size=14,
                                    margin = margin(0,0,-30,0)),
          plot.margin = unit(c(1.5,2,0.5,2), "cm"),
          legend.box.margin = margin(t=-30, b=32, l=0, unit='pt')
         ) +
    guides(fill = guide_legend(reverse=TRUE,
                               override.aes = list(shape = 15,
                                                   size = 6),
                               title.position="top"))

Readmission: A slightly higher number of patients were not readmitted to the hospital compared to those who were readmitted. The blue bar represents the number of patients who were readmitted, which is 11,754 (47.02%), while the orange bar represents the number of patients who were not readmitted, which is 13,246 (52.98%)

# Frequency Distribution Table (FDT) for the Readmission
readmitted_fdt <- readmissions %>%
	select(readmitted) %>%
	group_by(readmitted) %>%
	count() %>%
	ungroup() %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>%
	arrange(desc(n))

# Age
readmitted_bar_plot <- ggplot(readmitted_fdt) + 
	geom_chicklet(aes(x = fct_reorder(readmitted,n),
                      y = n), 
                   fill=c("#EE6C4D", "#98C1D9"),
                  color="white",
                  radius = grid::unit(1, "mm"), position="stack") +
	coord_flip() +
	ggtitle("Fig. 13: Bar Graph of the Patients' Readmission \n") +
	labs(y="\nNumber of patients", x="Readmitted\n") +
	theme_economist() + 
	scale_color_economist() + 
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          axis.ticks = element_blank(),
          legend.title = element_text(face="bold",
                                      size = 12),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 12),
          legend.box.margin = margin(t=0, b=0, l=-95, unit='pt'))  +
	scale_y_continuous(expand = c(0.01, 0),
                       limits = c(0, 14500),
                       breaks = seq(0, 14500, by=2000)) +
	scale_x_discrete(expand = c(0.52, 0),
					 labels = c("Yes", "No"))
readmitted_fdt
A tibble: 2 × 3
readmittednperc
<fct><int><chr>
no1324652.98%
yes1175447.02%

By Age

Numbers

The following statements can be said about the age groups’ hospital stay through the comparisons of their seven (7) discrete numerical features. In general,

Time in hospital: Groups within the age of [60-100) had the most number of hospital days of about four.</br> Number of procedures: Groups aged [40-80] had at least one medical procedure performed, whereas groups aged [80-100] had none; all age groups had a high number of laboratory procedures performed ranging from 43-46.</br> Number of medications: The [60-70) group had the most number of medications of 17; as the patient moves one age group away from it, the number decreases by 1 or 2. </br> Number of visits: Outpatient, inpatient, and emergency room visits were not very common (close to zero) before hospitalization for all age groups.

Categories

Medical specialty: We can see from Figure 14 graph the distribution of patients varies across different age groups and specialties. Among the patients with information about their physician’s specialty, most, if not all, age groups seem to be admitted by a physician of Internal Medicine, while specialties categorized as ‘Others’ were second.

# Summary statistics of age groups' time in hospital 
age_time_in_hospital_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(time_in_hospital)) %>%
	summarize(mean_time_in_hospital = mean(time_in_hospital),
              sd_time_in_hospital = sd(time_in_hospital),
              min_time_in_hospital = min(time_in_hospital),
              first_time_in_hospital = quantile(time_in_hospital, probs=0.25),
              median_time_in_hospital = median(time_in_hospital),
              third_quartile_time_in_hospital = quantile(time_in_hospital, probs=0.75),
              max_time_in_hospital = max(time_in_hospital)) %>%
	arrange(desc(median_time_in_hospital), desc(mean_time_in_hospital))

# Summary statistics of age groups' number of procedures
age_n_procedures_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(n_procedures)) %>%
	summarize(mean_n_procedures = mean(n_procedures),
              sd_n_procedures = sd(n_procedures),
              min_n_procedures = min(n_procedures),
              first_n_procedures = quantile(n_procedures, probs=0.25),
              median_n_procedures = median(n_procedures),
              third_n_procedures = quantile(n_procedures, probs=0.75),
              max_n_procedures = max(n_procedures)) %>%
	arrange(desc(median_n_procedures), desc(mean_n_procedures))

# Summary statistics of age groups' number of lab procedures
age_n_lab_procedures_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(n_lab_procedures)) %>%
	summarize(mean_n_lab_procedures = mean(n_lab_procedures),
              sd_n_lab_procedures = sd(n_lab_procedures),
              min_n_lab_procedures = min(n_lab_procedures),
              first_n_lab_procedures = quantile(n_lab_procedures, probs=0.25),
              median_n_lab_procedures = median(n_lab_procedures),
              third_n_lab_procedures = quantile(n_lab_procedures, probs=0.75),
              max_n_lab_procedures = max(n_lab_procedures))  %>%
	arrange(desc(median_n_lab_procedures), desc(mean_n_lab_procedures))

# Summary statistics of age groups' number of medications
age_n_medications_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(n_medications)) %>%
	summarize(mean_n_medications = mean(n_medications),
              sd_n_medications = sd(n_medications),
              min_n_medications = min(n_medications),
              first_n_medications = quantile(n_medications, probs=0.25),
              median_n_medications = median(n_medications),
              third_n_medications = quantile(n_medications, probs=0.75),
              max_n_medications = max(n_medications))  %>%
	arrange(desc(median_n_medications), desc(mean_n_medications))

# Summary statistics of age groups' number of outpatient visits
age_n_outpatient_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(n_outpatient)) %>%
	summarize(mean_n_outpatient = mean(n_outpatient),
              sd_n_outpatient = sd(n_outpatient),
              min_n_outpatient = min(n_outpatient),
              first_n_outpatient = quantile(n_outpatient, probs=0.25),
              median_n_outpatient = median(n_outpatient),
              third_n_outpatient = quantile(n_outpatient, probs=0.75),
              max_n_outpatient = max(n_outpatient))  %>%
	arrange(desc(median_n_outpatient), desc(mean_n_outpatient))

# Summary statistics of age groups' number of inpatient visits
age_n_inpatient_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(n_inpatient)) %>%
	summarize(mean_n_inpatient = mean(n_inpatient),
              sd_n_inpatient = sd(n_inpatient),
              min_n_inpatient = min(n_inpatient),
              first_n_inpatient = quantile(n_inpatient, probs=0.25),
              median_n_inpatient = median(n_inpatient),
              third_n_inpatient = quantile(n_inpatient, probs=0.75),
              max_n_inpatient = max(n_inpatient))  %>%
	arrange(desc(median_n_inpatient), desc(mean_n_inpatient))

# Summary statistics of age groups' number of ER visits
age_n_emergency_stats <- readmissions %>% 
	group_by(age) %>%
	filter(!is.na(age), !is.na(n_emergency)) %>%
	summarize(mean_n_emergency = mean(n_emergency),
              sd_n_emergency = sd(n_emergency),
              min_n_emergency = min(n_emergency),
              first_n_emergency = quantile(n_emergency, probs=0.25),
              median_n_emergency = median(n_emergency),
              third_n_emergency = quantile(n_emergency, probs=0.75),
              max_n_emergency = max(n_emergency))  %>%
	arrange(desc(median_n_emergency), desc(mean_n_emergency))


plyr::join_all(list(age_time_in_hospital_stats %>%
			   	select(age, median_time_in_hospital#, mean_time_in_hospital
					  ),
			   age_n_procedures_stats %>%
		      	select(age, median_n_procedures#, mean_n_procedures
					  ),
			   age_n_lab_procedures_stats %>%
			  	select(age, median_n_lab_procedures#, mean_n_lab_procedures
					  ),
			   age_n_medications_stats %>%
			  	select(age, median_n_medications#, mean_n_medications
					  ),
			   age_n_outpatient_stats %>%
			  	select(age, median_n_outpatient#, mean_n_outpatient
					  ),
			   age_n_inpatient_stats %>%
			  	select(age, median_n_inpatient#, mean_n_inpatient
					  ),
			   age_n_emergency_stats %>%
			  	select(age, median_n_emergency#, mean_n_emergency
					  )),
	by='age') %>%
		arrange(desc(age))

plyr::join_all(list(age_time_in_hospital_stats %>%
			   	select(age, mean_time_in_hospital
					  ),
			   age_n_procedures_stats %>%
		      	select(age, mean_n_procedures
					  ),
			   age_n_lab_procedures_stats %>%
			  	select(age, mean_n_lab_procedures
					  ),
			   age_n_medications_stats %>%
			  	select(age, mean_n_medications
					  ),
			   age_n_outpatient_stats %>%
			  	select(age, mean_n_outpatient
					  ),
			   age_n_inpatient_stats %>%
			  	select(age, mean_n_inpatient
					  ),
			   age_n_emergency_stats %>%
			  	select(age, mean_n_emergency
					  )),
	by='age') %>%
		arrange(desc(age))
A data.frame: 6 × 8
agemedian_time_in_hospitalmedian_n_proceduresmedian_n_lab_proceduresmedian_n_medicationsmedian_n_outpatientmedian_n_inpatientmedian_n_emergency
<fct><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
[90-100)404513000
[80-90)404614000
[70-80)414515000
[60-70)414416000
[50-60)314315000
[40-50)314414000
A data.frame: 6 × 8
agemean_time_in_hospitalmean_n_proceduresmean_n_lab_proceduresmean_n_medicationsmean_n_outpatientmean_n_inpatientmean_n_emergency
<fct><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
[90-100)4.7626670.685333343.9746713.873330.26133330.55733330.1386667
[80-90)4.8137730.969442044.3496515.295620.40079720.60451730.1472542
[70-80)4.5990931.376042143.5792016.361420.39651890.60114090.1351470
[60-70)4.3844071.599695642.5971617.223070.37578220.60747510.1603247
[50-60)4.1545371.518867942.4896716.699460.32704400.61185980.2295597
[40-50)4.0114531.298578242.9553715.316350.30213270.72077410.3957346
# Specialty of admitting physician by age group
age_and_medical_specialty_counts <- readmissions %>%
	group_by(age, medical_specialty) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Colorize the Physician's Specialty
color_scheme <- iwanthue(seed=1234, force_init=TRUE)
medical_specialty_colors <- color_scheme$hex(length(levels(factor(age_and_medical_specialty_counts$medical_specialty))))

# Bar plot
age_medical_specialty_bar_plot <- ggplot(age_and_medical_specialty_counts %>%
										 	filter(!is.na(medical_specialty))) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(medical_specialty, n)), 
                  color="white",
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 14: Stacked Bar Graph of the Patients' Age Groups by the\n                                  Specialty of the Admitting Physician\n") +
	labs(x="\nDiagnosis", y="Number of patients\n", fill="Specialty of the Admitting Physician: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=4,nrow=2,
                               reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),          
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = -0.9,
                                    size= 14),
          legend.box.margin = margin(t=0, b=0, l=-78, unit='pt')) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 3500, by=500)) + 
	scale_fill_manual(values = medical_specialty_colors)
age_and_medical_specialty_counts
A tibble: 42 × 4
agemedical_specialtynperc
<fct><fct><int><chr>
[40-50)NA118646.84%
[40-50)InternalMedicine 35213.90%
[40-50)Other 32212.72%
[40-50)Family/GeneralPractice 2349.24%
[40-50)Emergency/Trauma 2088.21%
[40-50)Surgery 1164.58%
[40-50)Cardiology 1144.50%
[50-60)NA212347.69%
[50-60)InternalMedicine 60813.66%
[50-60)Other 54612.26%
[50-60)Family/GeneralPractice 3367.55%
[50-60)Emergency/Trauma 3046.83%
[50-60)Cardiology 2906.51%
[50-60)Surgery 2455.50%
[60-70)NA297850.36%
[60-70)Other 71412.08%
[60-70)InternalMedicine 70611.94%
[60-70)Family/GeneralPractice 3966.70%
[60-70)Emergency/Trauma 3906.60%
[60-70)Cardiology 3836.48%
[60-70)Surgery 3465.85%
[70-80)NA336349.19%
[70-80)InternalMedicine105515.43%
[70-80)Other 72510.60%
[70-80)Family/GeneralPractice 4957.24%
[70-80)Emergency/Trauma 4626.76%
[70-80)Cardiology 4126.03%
[70-80)Surgery 3254.75%
[80-90)NA236052.26%
[80-90)InternalMedicine 70515.61%
[80-90)Emergency/Trauma 4309.52%
[80-90)Family/GeneralPractice 3497.73%
[80-90)Other 3197.06%
[80-90)Cardiology 1984.38%
[80-90)Surgery 1553.43%
[90-100)NA 37249.60%
[90-100)InternalMedicine 13918.53%
[90-100)Emergency/Trauma 9112.13%
[90-100)Family/GeneralPractice 729.60%
[90-100)Other 385.07%
[90-100)Surgery 263.47%
[90-100)Cardiology 121.60%

Diagnoses: Figures 15-16 demonstrates the patient distribution across age groups and primary, secondary, and additional secondary diagnoses. Diagnoses other than the six listed were given to patients in most, if not all, age groups among these three types of diagnosis.

# Primary diagnosis by age group
age_and_diag_1_counts <- readmissions %>%
	group_by(age, diag_1) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Colorize
color_scheme <- iwanthue(seed=1234, force_init=TRUE)
diag_1_colors <- color_scheme$hex(length(levels(factor(age_and_diag_1_counts$diag_1,
                                                      levels = c('Circulatory', 
                                                                 'Diabetes',
                                                                 'Digestive',
                                                                 'Injury',
                                                                 'Musculoskeletal',
                                                                 'Respiratory',
                                                                 'Other'),
                                                       order = TRUE))))

# Bar plot
age_diag_bar_plot <- ggplot(age_and_diag_1_counts %>%
								filter(!is.na(diag_1))) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(diag_1,n)), 
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 15: Stacked Bar Graph of the Patients' Age Groups by Primary Diagnoses\n") +
	labs(x="", y="Number of patients\n", fill="Diagnosis: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=4,nrow=2,
                               reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="none",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),        
          axis.title.x=element_blank(),
          axis.text.x=element_blank(),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 11),
          legend.box.margin = margin(t=0, b=0, l=-95, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 7500, by=2000)) +
	scale_fill_manual(values = diag_1_colors)

# Secondary diagnosis by age group
age_and_diag_2_counts <- readmissions %>%
	group_by(age, diag_2) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Colorize
color_scheme2 <- iwanthue(seed=1234, force_init=TRUE)
diag_2_colors <- color_scheme2$hex(length(levels(factor(age_and_diag_2_counts$diag_2,
                                                      levels = c('Circulatory', 
                                                                 'Diabetes',
                                                                 'Digestive',
                                                                 'Injury',
                                                                 'Musculoskeletal',
                                                                 'Respiratory',
                                                                 'Other'),
                                                       order = TRUE))))

# Bar plot
age_diag_2_bar_plot <- ggplot(age_and_diag_2_counts %>%
								filter(!is.na(diag_2))) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(diag_2,n)), 
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 16: Stacked Bar Graph of the Patients' Age Groups by Secondary Diagnoses\n") +
	labs(x="", y="Number of patients\n", fill="Secondary Diagnosis: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=4,nrow=2,
                               reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="none",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),     
          axis.title.x=element_blank(),
          axis.text.x=element_blank(),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 11),
          legend.box.margin = margin(t=0, b=-100, l=-100, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 7500, by=2000)) +
	scale_fill_manual(values = diag_1_colors)


# Additional Secondary diagnosis by age group
age_and_diag_3_counts <- readmissions %>%
	group_by(age, diag_3) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Colorize
color_scheme <- iwanthue(seed=1234, force_init=TRUE)
diag_3_colors <- color_scheme$hex(length(levels(factor(age_and_diag_3_counts$diag_3,
                                                      levels = c('Circulatory', 
                                                                 'Diabetes',
                                                                 'Digestive',
                                                                 'Injury',
                                                                 'Musculoskeletal',
                                                                 'Respiratory',
                                                                 'Other'),
                                                       order = TRUE))))

# Bar plot
age_diag_3_bar_plot <- ggplot(age_and_diag_3_counts %>%
								filter(!is.na(diag_3))) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(diag_3,n)),  
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 17: Stacked Bar Graph of the Patients' Age Groups by Additional Secondary Diagnoses\n") +
	labs(x="\nAge group", y="Number of patients\n", fill="Diagnosis: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=4,nrow=2,
                               reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(), 
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 10),
          legend.box.margin = margin(t=0, b=0, l=-110, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 7500, by=2000)) +
	scale_fill_manual(values = diag_3_colors)

#ggarrange(age_diag_bar_plot, 
#          age_diag_2_bar_plot,
#          age_diag_3_bar_plot,
#          ncol = 1, nrow = 3,
#          heights = c(0.9,0.9,1.65),
#          align = "v")
age_and_diag_1_counts
age_and_diag_2_counts
age_and_diag_3_counts
A tibble: 45 × 4
agediag_1nperc
<fct><fct><int><chr>
[40-50)Other 75029.62%
[40-50)Circulatory 50419.91%
[40-50)Respiratory 37614.85%
[40-50)Diabetes 36914.57%
[40-50)Digestive 27110.70%
[40-50)Injury 1626.40%
[40-50)Musculoskeletal 1003.95%
[50-60)Circulatory125628.21%
[50-60)Other116426.15%
[50-60)Respiratory 69415.59%
[50-60)Digestive 4429.93%
[50-60)Diabetes 3938.83%
[50-60)Injury 2736.13%
[50-60)Musculoskeletal 2305.17%
[60-70)Circulatory196233.18%
[60-70)Other140223.71%
[60-70)Respiratory 83614.14%
[60-70)Digestive 5549.37%
[60-70)Injury 4006.76%
[60-70)Diabetes 3856.51%
[60-70)Musculoskeletal 3736.31%
[60-70)NA 10.02%
[70-80)Circulatory239234.99%
[70-80)Other169324.76%
[70-80)Respiratory 96414.10%
[70-80)Digestive 5858.56%
[70-80)Injury 4446.49%
[70-80)Diabetes 3855.63%
[70-80)Musculoskeletal 3735.46%
[70-80)NA 10.01%
[80-90)Circulatory148232.82%
[80-90)Other126928.10%
[80-90)Respiratory 69115.30%
[80-90)Digestive 4028.90%
[80-90)Injury 3217.11%
[80-90)Diabetes 1814.01%
[80-90)Musculoskeletal 1683.72%
[80-90)NA 20.04%
[90-100)Circulatory 22830.40%
[90-100)Other 22029.33%
[90-100)Respiratory 11915.87%
[90-100)Digestive 7510.00%
[90-100)Injury 668.80%
[90-100)Diabetes 344.53%
[90-100)Musculoskeletal 81.07%
A tibble: 47 × 4
agediag_2nperc
<fct><fct><int><chr>
[40-50)Other109743.33%
[40-50)Circulatory 52620.77%
[40-50)Diabetes 46218.25%
[40-50)Respiratory 1817.15%
[40-50)Digestive 1295.09%
[40-50)Injury 773.04%
[40-50)Musculoskeletal 532.09%
[40-50)NA 70.28%
[50-60)Other158735.65%
[50-60)Circulatory126628.44%
[50-60)Diabetes 70515.84%
[50-60)Respiratory 47710.71%
[50-60)Digestive 2104.72%
[50-60)Musculoskeletal 1022.29%
[50-60)Injury 1002.25%
[50-60)NA 50.11%
[60-70)Other203634.43%
[60-70)Circulatory196533.23%
[60-70)Respiratory 71712.13%
[60-70)Diabetes 68711.62%
[60-70)Digestive 2524.26%
[60-70)Injury 1402.37%
[60-70)Musculoskeletal 1071.81%
[60-70)NA 90.15%
[70-80)Circulatory248336.32%
[70-80)Other233934.21%
[70-80)Respiratory 84012.29%
[70-80)Diabetes 6759.87%
[70-80)Digestive 2273.32%
[70-80)Injury 1622.37%
[70-80)Musculoskeletal 1031.51%
[70-80)NA 80.12%
[80-90)Other169137.44%
[80-90)Circulatory161335.72%
[80-90)Respiratory 57512.73%
[80-90)Diabetes 3307.31%
[80-90)Digestive 1363.01%
[80-90)Injury 1022.26%
[80-90)Musculoskeletal 561.24%
[80-90)NA 130.29%
[90-100)Other 30640.80%
[90-100)Circulatory 28137.47%
[90-100)Respiratory 8210.93%
[90-100)Diabetes 476.27%
[90-100)Digestive 192.53%
[90-100)Injury 101.33%
[90-100)Musculoskeletal 50.67%
A tibble: 48 × 4
agediag_3nperc
<fct><fct><int><chr>
[40-50)Other108442.81%
[40-50)Diabetes 52820.85%
[40-50)Circulatory 52020.54%
[40-50)Respiratory 1355.33%
[40-50)Digestive 1295.09%
[40-50)Injury 532.09%
[40-50)NA 491.94%
[40-50)Musculoskeletal 341.34%
[50-60)Other163536.73%
[50-60)Circulatory122927.61%
[50-60)Diabetes 87519.65%
[50-60)Respiratory 2906.51%
[50-60)Digestive 2004.49%
[50-60)Musculoskeletal 1012.27%
[50-60)Injury 741.66%
[50-60)NA 481.08%
[60-70)Other206834.97%
[60-70)Circulatory183931.10%
[60-70)Diabetes104217.62%
[60-70)Respiratory 4707.95%
[60-70)Digestive 2143.62%
[60-70)Injury 1252.11%
[60-70)Musculoskeletal 1141.93%
[60-70)NA 410.69%
[70-80)Other238334.85%
[70-80)Circulatory229233.52%
[70-80)Diabetes108215.83%
[70-80)Respiratory 5588.16%
[70-80)Digestive 2353.44%
[70-80)Musculoskeletal 1301.90%
[70-80)Injury 1241.81%
[70-80)NA 330.48%
[80-90)Other164536.43%
[80-90)Circulatory154234.15%
[80-90)Diabetes 63314.02%
[80-90)Respiratory 4048.95%
[80-90)Digestive 1222.70%
[80-90)Injury 801.77%
[80-90)Musculoskeletal 671.48%
[80-90)NA 230.51%
[90-100)Other 29238.93%
[90-100)Circulatory 26435.20%
[90-100)Diabetes 10113.47%
[90-100)Respiratory 587.73%
[90-100)Digestive 162.13%
[90-100)Musculoskeletal 91.20%
[90-100)Injury 81.07%
[90-100)NA 20.27%

Prediabetes test results: For patients who took a glucose test, the distributions of ‘Normal’ and ‘High’ results appear to be similar across age groups, while the majority of patients across age groups who took an A1C test had a ‘High’ result.

# Glucose test result by age group
age_and_glucose_test_counts <- readmissions %>%
	group_by(age, glucose_test) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Bar plot
age_glucose_test_bar_plot <- ggplot(age_and_glucose_test_counts %>%
										filter(glucose_test != "no")) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(glucose_test,n)), 
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 18: Stacked Bar Graph of the Patients' Age Groups by Glucose Prediabetes Test Result\n") +
	labs(x="", y="Number of patients\n", fill="Test Result: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="none",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),        
          axis.title.x=element_blank(),
          axis.text.x=element_blank(),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 10),
          legend.box.margin = margin(t=0, b=0, l=-95, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 400, by=100)) +
	scale_fill_manual(values = c("#8BD69D", "#BD3E38"),
                      labels = c("Normal", "High")
                     )

# A1C by age group
age_and_A1Ctest_counts <- readmissions %>%
	group_by(age, A1Ctest) %>%
	filter(age != "Missing", A1Ctest != "Missing") %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Bar plot
age_A1Ctest_bar_plot <- ggplot(age_and_A1Ctest_counts %>%
							   		filter(A1Ctest != "no")) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(A1Ctest,n)),  
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 19: Stacked Bar Graph of the Patients' Age Groups by A1C Prediabetes Test Result       \n") +
	labs(x="\nAge group", y="Number of patients\n", fill="Test Result: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(), 
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 10),
          legend.box.margin = margin(t=0, b=0, l=-320, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                      breaks = seq(0, 850, by=200)) +
	scale_fill_manual(values = c("#8BD69D", "#BD3E38"),
                      labels = c("Normal", "High")
                     )

#ggarrange(age_glucose_test_bar_plot, 
#          age_A1Ctest_bar_plot,
#          ncol = 1, nrow = 2,
#          heights = c(0.85,1.4),
#          align = "v")
age_and_glucose_test_counts %>%
	filter(glucose_test!="no")
age_and_A1Ctest_counts
A tibble: 12 × 4
ageglucose_testnperc
<fct><fct><int><chr>
[40-50)high 823.24%
[40-50)normal 592.33%
[50-60)normal1002.25%
[50-60)high 881.98%
[60-70)normal1432.42%
[60-70)high1272.15%
[70-80)high1982.90%
[70-80)normal1972.88%
[80-90)normal1593.52%
[80-90)high1563.45%
[90-100)high 354.67%
[90-100)normal 314.13%
A tibble: 18 × 4
ageA1Ctestnperc
<fct><fct><int><chr>
[40-50)no193876.54%
[40-50)high 44717.65%
[40-50)normal 1475.81%
[50-60)no356079.96%
[50-60)high 63114.17%
[50-60)normal 2615.86%
[60-70)no499084.39%
[60-70)high 68311.55%
[60-70)normal 2404.06%
[70-80)no588586.08%
[70-80)high 6269.16%
[70-80)normal 3264.77%
[80-90)no388686.05%
[80-90)high 3968.77%
[80-90)normal 2345.18%
[90-100)no 67990.53%
[90-100)high 445.87%
[90-100)normal 273.60%

Diabetes medication: In all age groups, people with a prescription and a change in diabetes medication outnumbered those without a prescription and no change.

# Change in diabestes medication by age group
age_and_change_counts <- readmissions %>%
	group_by(age, change) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Bar plot
age_change_bar_plot <- ggplot(age_and_change_counts) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(change,n)), 
                  #color="white",
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 20: Stacked Bar Graph of the Patient's Response to the Question\n              Related to the Change in Diabetes Medication\n") +
	labs(x="", y="Number of patients\n", fill="Response: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(reverse = TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="none",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),        
          axis.title.x=element_blank(),
          axis.text.x=element_blank(),
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 11.5),
          legend.box.margin = margin(t=0, b=0, l=-92, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 7500, by=2000)) +
    scale_fill_manual(values = c("#EE6C4D", "#98C1D9"),
                      labels = c("No", "Yes")
                     ) 

# A1C by age group
age_and_diabetes_med_counts <- readmissions %>%
	group_by(age, diabetes_med) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Bar plot
age_diabetes_med_bar_plot <- ggplot(age_and_diabetes_med_counts) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(diabetes_med,n)),  
                  #color="white",
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 21: Stacked Bar Graph of the Patient's Response to the Question\n               Related to the Prescription of a Diabetes Medication\n") +
	labs(x="\nAge group", y="Number of patients\n", fill="Response: ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(ncol=3,nrow=1,
                               reverse = TRUE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 11.5),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(), 
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 11.5),
          legend.box.margin = margin(t=0, b=0, l=-305, unit='pt')
         ) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 7500, by=2000)) +
    scale_fill_manual(values = c("#EE6C4D", "#98C1D9"),
                      labels = c("No", "Yes")
                     )


#ggarrange(age_change_bar_plot, 
#          age_diabetes_med_bar_plot,#+
#          	#rremove("x.text"), 
#          ncol = 1, nrow = 2,
#          heights = c(0.85,1.4),
#          align = "v")

Readmission: Although all of the age groups have patients who mostly had not readmitted, the difference between their readmissions and non-readmissions seem to be little.

# Readmission by age group
age_and_readmitted_counts <- readmissions %>%
	group_by(age, readmitted) %>%
	summarize(n = n(), .groups = "drop_last") %>%
	mutate(perc = label_percent(accuracy=0.01)(n/sum(n))) %>% 
	arrange(age, desc(n)) %>%
	ungroup()

# Bar plot
age_readmitted_bar_plot <- ggplot(age_and_readmitted_counts) + 
	geom_chicklet(aes(x = age, y = n,
                      fill = fct_reorder(readmitted, n)), 
                  color="white",
                  radius = grid::unit(1, "mm"), position="stack") +
	ggtitle("Fig. 22: Stacked Bar Graph of the Patients' Age Groups by Readmission\n") +
	labs(x="\nDiagnosis", y="Number of patients\n", fill="Readmitted ") +
	scale_x_discrete(expand = c(0.01, 0)) + 
	theme_economist() + 
	scale_color_economist() + 
    guides(fill = guide_legend(reverse = FALSE,
                               override.aes = list(shape = 15,
                                                   size = 4),
                               title.position="top")) +
	theme(legend.position="bottom",
          legend.text = element_text(margin = margin(r = 2, unit = "pt"),
                                     size = 10),
          legend.title = element_text(face="bold",
                                      size = 12),
          axis.ticks = element_blank(),          
          panel.grid.minor = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
		  panel.grid.major = element_line(color="grey",
                                          linetype="dashed",
                                          linewidth=0.3),
          plot.title = element_text(hjust = 0,
                                    size= 12),
          legend.box.margin = margin(t=0, b=0, l=-338, unit='pt')) +
	scale_y_continuous(expand = c(0.01, 0),
                       breaks = seq(0, 6000, by=1000)) +
    scale_fill_manual(values = c("#EE6C4D", "#98C1D9"),
                      labels = c("Yes", "No")
                     )
age_and_readmitted_counts
A tibble: 12 × 4
agereadmittednperc
<fct><fct><int><chr>
[40-50)no140555.49%
[40-50)yes112744.51%
[50-60)no248655.84%
[50-60)yes196644.16%
[60-70)no314353.15%
[60-70)yes277046.85%
[70-80)no350151.21%
[70-80)yes333648.79%
[80-90)no227750.42%
[80-90)yes223949.58%
[90-100)no 43457.87%
[90-100)yes 31642.13%

Patient Readmissions

In this section, the patients’ readmission will be analyzed by different representing features through contingency tables, graphs, and regression analysis.

As previously mentioned, the number of readmitted patients is 11,754 which translates to an overall readmission rate of 47.02%.

By Variable

The table below shows the comparisons of means and medians of the readmitted, not readmitted, and overall patients in terms of the seven (7) numeric features. We can see that the three sets seem to be the same in characteristics.

as.data.frame(xtabs(~ readmitted, data = readmissions)) %>%
	rename(n_patients = Freq) %>%
	mutate(rate=n_patients/sum(n_patients))
A data.frame: 2 × 3
readmittedn_patientsrate
<fct><int><dbl>
no132460.52984
yes117540.47016
# Summary statistics for numerical variables of readmitted patients
readmitted_sum_stats <- data.frame(
    Variable = readmissions %>%
		select_if(is.numeric) %>%
		colnames) %>%
	bind_cols(as.data.frame(t(readmissions %>% filter(readmitted == "yes") %>%
                              summarise_if(is.numeric, list(mean)) %>%
                              bind_rows(readmissions %>% filter(readmitted == "yes") %>%
                                        	summarise_if(is.numeric, list(sd)), 
                                        readmissions %>% filter(readmitted == "yes") %>%
                                        	summarise_if(is.numeric, list(min)),
                                        readmissions %>% filter(readmitted == "yes") %>%
                                        	summarise_if(is.numeric, list(median)),
                                        readmissions %>% filter(readmitted == "yes") %>%
                                        	summarise_if(is.numeric, list(max)))
                             )) %>%
              rename(Mean = V1,
                     `Std. Dev.` = V2,
                     `Min.` = V3,
                     `Median` = V4,
                     `Max.` = V5))

rownames(readmitted_sum_stats) <- 1: nrow(readmitted_sum_stats)

# Summary statistics for numerical variables of not readmitted patients
not_readmitted_sum_stats <- data.frame(
    Variable = readmissions %>%
		select_if(is.numeric) %>%
		colnames) %>%
	bind_cols(as.data.frame(t(readmissions %>% filter(readmitted == "no") %>%
                              summarise_if(is.numeric, list(mean)) %>%
                              bind_rows(readmissions %>% filter(readmitted == "no") %>%
                                        	summarise_if(is.numeric, list(sd)), 
                                        readmissions %>% filter(readmitted == "no") %>%
                                        	summarise_if(is.numeric, list(min)),
                                        readmissions %>% filter(readmitted == "no") %>%
                                        	summarise_if(is.numeric, list(median)),
                                        readmissions %>% filter(readmitted == "no") %>%
                                        	summarise_if(is.numeric, list(max)))
                             )) %>%
              rename(Mean = V1,
                     `Std. Dev.` = V2,
                     `Min.` = V3,
                     `Median` = V4,
                     `Max.` = V5))

rownames(not_readmitted_sum_stats) <- 1: nrow(not_readmitted_sum_stats)

# Med
readmitted_sum_stats %>%
	select(Variable, Mean, Median) %>%
	rename(readm_Mean = Mean, readm_Median = Median) %>%
		bind_cols(not_readmitted_sum_stats %>%
				  	select(Mean, Median) %>%
				  	rename(not_readm_Mean = Mean, not_readm_Median = Median),
				  sum_stats %>%
				  	select(Mean, Median) %>%
				  	rename(overall_Mean = Mean, overall_Median = Median)
				 )
A data.frame: 7 × 7
Variablereadm_Meanreadm_Mediannot_readm_Meannot_readm_Medianoverall_Meanoverall_Median
<chr><dbl><dbl><dbl><dbl><dbl><dbl>
time_in_hospital 4.5907776 4 4.3313453 4 4.45332 4
n_lab_procedures43.93440534542.62524544443.2407644
n_procedures 1.2713970 1 1.4242035 1 1.35236 1
n_medications16.56789181615.97244451516.2524015
n_outpatient 0.4875787 0 0.2588706 0 0.36640 0
n_inpatient 0.8816573 0 0.3801902 0 0.61596 0
n_emergency 0.2745448 0 0.1085611 0 0.18660 0
#readmissions %>%
#	group_by(readmitted) %>%
#	summarize(count = n(),
#			  median = median(time_in_hospital, na.rm = TRUE),
#			  IQR = IQR(time_in_hospital, na.rm = TRUE))
 
#ggboxplot(readmissions, x = "readmitted", y = "time_in_hospital",
#          color = "readmitted", palette = c("#FFA500", "#FF0000"),
#          ylab = "times_in_hospital", xlab = "readmitted?")
 
wilcox.test(time_in_hospital ~ readmitted,
                   data = readmissions,
                   exact = FALSE)

wilcox.test(n_procedures ~ readmitted,
                   data = readmissions,
                   exact = FALSE)

wilcox.test(n_lab_procedures ~ readmitted,
                   data = readmissions,
                   exact = FALSE)

wilcox.test(n_medications ~ readmitted,
                   data = readmissions,
                   exact = FALSE)

wilcox.test(n_outpatient ~ readmitted,
                   data = readmissions,
                   exact = FALSE)

wilcox.test(n_inpatient ~ readmitted,
                   data = readmissions,
                   exact = FALSE)

wilcox.test(n_emergency ~ readmitted,
                   data = readmissions,
                   exact = FALSE)
	Wilcoxon rank sum test with continuity correction

data:  time_in_hospital by readmitted
W = 73042702, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0





	Wilcoxon rank sum test with continuity correction

data:  n_procedures by readmitted
W = 81897160, p-value = 5.333e-14
alternative hypothesis: true location shift is not equal to 0





	Wilcoxon rank sum test with continuity correction

data:  n_lab_procedures by readmitted
W = 74776296, p-value = 6.973e-08
alternative hypothesis: true location shift is not equal to 0





	Wilcoxon rank sum test with continuity correction

data:  n_medications by readmitted
W = 71996398, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0





	Wilcoxon rank sum test with continuity correction

data:  n_outpatient by readmitted
W = 70962944, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0





	Wilcoxon rank sum test with continuity correction

data:  n_inpatient by readmitted
W = 61536228, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0





	Wilcoxon rank sum test with continuity correction

data:  n_emergency by readmitted
W = 72302580, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0

The table below shows the readmissions and rates by category of each factor arranged descendingly.

#
readmitted_age <- as.data.frame(xtabs(~ readmitted + age, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(age) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup()

#
readmitted_medical_specialty <- as.data.frame(xtabs(~ readmitted + medical_specialty, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(medical_specialty) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup()

#
readmitted_diag_1 <- as.data.frame(xtabs(~ readmitted + diag_1, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(diag_1) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_diag_2 <- as.data.frame(xtabs(~ readmitted + diag_2, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(diag_2) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_diag_3 <- as.data.frame(xtabs(~ readmitted + diag_3, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(diag_3) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_glucose_test <- as.data.frame(xtabs(~ readmitted + glucose_test, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(glucose_test) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_A1Ctest <- as.data.frame(xtabs(~ readmitted + A1Ctest, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(A1Ctest) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_change <- as.data.frame(xtabs(~ readmitted + change, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(change) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_diabetes_med <- as.data.frame(xtabs(~ readmitted + diabetes_med, data = readmissions)) %>%
	filter(readmitted == "yes") %>%
	group_by(diabetes_med) %>%
	summarize(readmissions=sum(Freq), rate=sum(Freq)/25000, .groups = "keep") %>%
	arrange(desc(readmissions)) %>%
	ungroup() 

#
readmitted_factor <- rbind(readmitted_age %>% rename(category = age) %>% mutate(factor = "age"),
	readmitted_medical_specialty %>% rename(category = medical_specialty) %>% mutate(factor = "medical_specialty"),
	readmitted_diag_1 %>% rename(category = diag_1) %>% mutate(factor = "diag_1"),
	readmitted_diag_2 %>% rename(category = diag_2) %>% mutate(factor = "diag_2"),
	readmitted_diag_3 %>% rename(category = diag_3) %>% mutate(factor = "diag_3"),
	readmitted_glucose_test %>% rename(category = glucose_test) %>% mutate(factor = "glucose_test"),
	readmitted_A1Ctest %>% rename(category = A1Ctest) %>% mutate(factor = "A1Ctest"),
	readmitted_change %>% rename(category = change) %>% mutate(factor = "change"),
	readmitted_diabetes_med %>% rename(category = diabetes_med) %>% mutate(factor = "diabetes_med")
)

readmitted_factor %>%
	select(factor, everything())
A tibble: 47 × 4
factorcategoryreadmissionsrate
<chr><fct><int><dbl>
age[70-80) 33360.13344
age[60-70) 27700.11080
age[80-90) 22390.08956
age[50-60) 19660.07864
age[40-50) 11270.04508
age[90-100) 3160.01264
medical_specialtyInternalMedicine 15960.06384
medical_specialtyOther 11050.04420
medical_specialtyFamily/GeneralPractice 9320.03728
medical_specialtyEmergency/Trauma 9310.03724
medical_specialtyCardiology 6340.02536
medical_specialtySurgery 5000.02000
medical_specialtyMissing 00.00000
diag_1Circulatory 37500.15000
diag_1Other 29320.11728
diag_1Respiratory 18060.07224
diag_1Digestive 11050.04420
diag_1Diabetes 9370.03748
diag_1Injury 7270.02908
diag_1Musculoskeletal 4950.01980
diag_1Missing 00.00000
diag_2Other 42480.16992
diag_2Circulatory 39320.15728
diag_2Respiratory 14060.05624
diag_2Diabetes 12830.05132
diag_2Digestive 4310.01724
diag_2Injury 2400.00960
diag_2Musculoskeletal 1970.00788
diag_2Missing 00.00000
diag_3Other 42530.17012
diag_3Circulatory 37120.14848
diag_3Diabetes 19470.07788
diag_3Respiratory 9540.03816
diag_3Digestive 4300.01720
diag_3Musculoskeletal 2050.00820
diag_3Injury 1970.00788
diag_3Missing 00.00000
glucose_testno110640.44256
glucose_testhigh 3570.01428
glucose_testnormal 3330.01332
A1Ctestno 99350.39740
A1Ctesthigh 12990.05196
A1Ctestnormal 5200.02080
changeno 60770.24308
changeyes 56770.22708
diabetes_medyes 93670.37468
diabetes_medno 23870.09548

Model

Since the feature representing a patient’s readmission takes on two values, ‘yes’ or ‘no’, it is used as the dependent variable of a multivariate logistic regression model in order to predict the odds of readmission. Also, not all of the patient’s features are used as independent variables, that is, variables medical_specialty, glucose_test, and A1Ctest were excluded due to large number of missing values. Variables with few missing values (diag_1, diag_2, and diag_3) were imputed by their respective modes.

The reference category for each factor variable is:

  • age: [40-50)
  • diag_1, diag_2, and diag_3: Circulatory
  • change: no
  • diabetes_med: no

Below are the estimates of the coefficients along with their standard errors, t-statistics, p-values, odds ratios (ORs), and 95% CIs of the ORs.

## Univariate Regression Analysis
logstc_model_age <- glm(readmitted ~ age, data=readmissions, family="binomial"(link=logit))

logstc_model_time_in_hospital <- glm(readmitted ~ time_in_hospital, data=readmissions, family="binomial"(link=logit))

logstc_model_n_procedures <- glm(readmitted ~ n_procedures, data=readmissions, family="binomial"(link=logit))

logstc_model_n_lab_procedures <- glm(readmitted ~ n_lab_procedures, data=readmissions, family="binomial"(link=logit))

logstc_model_n_medications <- glm(readmitted ~ n_medications, data=readmissions, family="binomial"(link=logit))

logstc_model_n_outpatient <- glm(readmitted ~ n_outpatient, data=readmissions, family="binomial"(link=logit))

logstc_model_n_inpatient <- glm(readmitted ~ n_inpatient, data=readmissions, family="binomial"(link=logit))

logstc_model_n_emergency <- glm(readmitted ~ n_emergency, data=readmissions, family="binomial"(link=logit))

logstc_model_medical_specialty <- glm(readmitted ~ medical_specialty, data=readmissions, family="binomial"(link=logit))

logstc_model_diag_1 <- glm(readmitted ~ diag_1, data=readmissions, family="binomial"(link=logit))

logstc_model_diag_2 <- glm(readmitted ~ diag_2, data=readmissions, family="binomial"(link=logit))

logstc_model_diag_3 <- glm(readmitted ~ diag_3, data=readmissions, family="binomial"(link=logit))

logstc_model_change <- glm(readmitted ~ change, data=readmissions, family="binomial"(link=logit))

logstc_model_diabetes_med <- glm(readmitted ~ diabetes_med, data=readmissions, family="binomial"(link=logit))

# Install and load the "questionr" package
# For calculating the odds ratio									   
suppressWarnings(suppressMessages(install.packages("questionr")))
suppressPackageStartupMessages(library(questionr))

#
#as.data.frame(summary.lm(logstc_model_age)$coefficients) %>%
#	rownames_to_column("Variable") %>%
#	mutate(`Signif. Code` = case_when(`Pr(>|t|)` < 0.001 ~  "***",
#                                      `Pr(>|t|)` >= 0.001 & `Pr(>|t|)` < 0.01 ~ "**",
#                                      `Pr(>|t|)` >= 0.01 & `Pr(>|t|)` < 0.05 ~ "*",
#                                      `Pr(>|t|)` >= 0.05 & `Pr(>|t|)` < 0.1 ~ ".",
#                                       TRUE ~ "")) %>%
#	merge(odds.ratio(logstc_model_age, 0.95) %>% 
#		  	rownames_to_column("Variable") %>%
#		  	select(-p))

# Create mode() function to calculate mode
mode <- function(x, na.rm = FALSE) {
  if(na.rm){ #if na.rm is TRUE, remove NA values from input x
    x = x[!is.na(x)]
  }
  val <- unique(x)
  return(val[which.max(tabulate(match(x, val)))])
}


## Multivariate Regression Analysis

data_for_regression <- readmissions %>% 
	select(-c(medical_specialty, glucose_test, A1Ctest)) %>%
	mutate_all(~case_when(is.character(.) & is.na(.) ~ mode(.),
						  TRUE ~ .))

# Logistics Regression Model
logstc_model <- glm(readmitted ~ ., data=data_for_regression, family="binomial"(link=logit))

# Summary statistics of the full model
#paste("Residual standard error:", round(summary.lm(full_model)$sigma, 4), 
#      " ,  R-square: ", round(summary.lm(full_model)$r.squared, 4), 
#      " ,  Adj. R-square: ", round(summary.lm(full_model)$adj.r.squared, 4))

# Full model's table of estimated coefficients, their SEs, t-stats, and (two-sided) p-values
summary_logstc <- as.data.frame(summary.lm(logstc_model)$coefficients) %>%
	rownames_to_column("Variable") %>%
	mutate(`Signif. Code` = case_when(`Pr(>|t|)` < 0.001 ~  "***",
                                      `Pr(>|t|)` >= 0.001 & `Pr(>|t|)` < 0.01 ~ "**",
                                      `Pr(>|t|)` >= 0.01 & `Pr(>|t|)` < 0.05 ~ "*",
                                      `Pr(>|t|)` >= 0.05 & `Pr(>|t|)` < 0.1 ~ ".",
                                       TRUE ~ "")) %>%
	merge(odds.ratio(logstc_model, 0.95) %>% 
		  	rownames_to_column("Variable") %>%
		  	select(-p))
Waiting for profiling to be done...
summary_logstc
A data.frame: 33 × 9
VariableEstimateStd. Errort valuePr(>|t|)Signif. CodeOR2.5 %97.5 %
<chr><dbl><dbl><dbl><dbl><chr><dbl><dbl><dbl>
(Intercept)-0.6763086640.0727457345-9.29688413 1.562023e-20***0.50849050.44333590.5830338
age[50-60) 0.0275800890.0552481797 0.49920358 6.176404e-011.02796390.92648331.1407389
age[60-70) 0.1401388150.0531046658 2.63891718 8.322339e-03**1.15043351.04108701.2715419
age[70-80) 0.2083658680.0523118146 3.98315122 6.820194e-05***1.23166371.11627131.3593055
age[80-90) 0.2209603790.0559845407 3.94681061 7.941792e-05***1.24727401.12261121.3860596
age[90-100)-0.0530549190.0918668717-0.57751960 5.635938e-010.94832790.79736161.1269743
changeyes 0.0395098490.0325303449 1.21455365 2.245480e-011.04030070.97850751.1060109
diabetes_medyes 0.2275335050.0381635967 5.96205611 2.524595e-09***1.25549951.16850241.3490779
diag_1Diabetes 0.1480484570.0612105412 2.41867584 1.558428e-02*1.15956911.03340181.3012846
diag_1Digestive-0.0131400420.0542553278-0.24218898 8.086357e-010.98694590.89106781.0930423
diag_1Injury-0.1881719500.0606963642-3.10021782 1.935954e-03**0.82847220.73887910.9286184
diag_1Musculoskeletal-0.2276024780.0693867245-3.28020207 1.038761e-03**0.79644080.69864020.9072697
diag_1Other-0.1665686330.0393675922-4.23111052 2.333769e-05***0.84656470.78606920.9116689
diag_1Respiratory-0.0376302830.0451369154-0.83369195 4.044626e-010.96306890.88459031.0484649
diag_2Diabetes-0.0519291570.0495084120-1.04889564 2.942364e-010.94939610.86485071.0420843
diag_2Digestive-0.1559346540.0775036909-2.01196423 4.423453e-02*0.85561510.73919570.9897442
diag_2Injury-0.1789889230.0948599735-1.88687511 5.918882e-02.0.83611520.69878150.9989114
diag_2Musculoskeletal-0.0338570490.1107840497-0.30561303 7.599019e-010.96670970.78421801.1904138
diag_2Other-0.0770840240.0351261254-2.19449266 2.820927e-02*0.92581210.86656320.9891005
diag_2Respiratory-0.0652647650.0477940091-1.36554279 1.720949e-010.93681940.85616991.0249865
diag_3Diabetes-0.0469634220.0423694828-1.10842565 2.676888e-010.95412230.88094861.0333233
diag_3Digestive-0.0018434990.0777562600-0.02370869 9.810852e-010.99815820.86203711.1553276
diag_3Injury-0.1200780260.1048401374-1.14534403 2.520777e-010.88685120.72731601.0795854
diag_3Musculoskeletal-0.0789509190.1062193390-0.74328197 4.573180e-010.92408530.75605181.1280833
diag_3Other-0.0794706750.0342788439-2.31835925 2.043791e-02*0.92360510.86587850.9851707
diag_3Respiratory-0.0050925670.0554708711-0.09180615 9.268528e-010.99492040.89622131.1044124
n_emergency 0.2163282830.0264002294 8.19418195 2.643943e-16***1.24150991.18221931.3057433
n_inpatient 0.3838278890.015028170225.540560324.841353e-142***1.46789281.42720551.5102947
n_lab_procedures 0.0010635780.0007531879 1.41210218 1.579325e-011.00106410.99964581.0024849
n_medications 0.0013894910.0021909349 0.63420012 5.259561e-011.00139050.99726691.0055284
n_outpatient 0.1208906350.0137120597 8.81637317 1.258480e-18***1.12850151.10008701.1583729
n_procedures-0.0438694700.0091983519-4.76927502 1.859425e-06***0.95707890.94063290.9737829
time_in_hospital 0.0178437370.0054244633 3.28949358 1.005080e-03**1.01800391.00766141.0284549
Odds Ratios

To interpret the odds ratios in the model, we will separate them into categorical and numerical variables once more.

The odds ratio for categorical data is the percentage increase (or decrease) in the odds of readmission among patients within a particular case-category compared to those in the control or reference group. Therefore:

  1. Patients in the [80-90], [70-80], and [60-70] age groups have 24.73%, 23.17%, and 15.04% higher odds of readmission, respectively, than those in the [40-50] group.
  2. Patients with diabetes as their primary diagnosis had a 15.96% greater odds of readmission than those with a circulatory diagnosis. On the other hand, those with a secondary and additional secondary diagnosis of diabetes had a 5.06% and 4.59% decrease, respectively, as compared to those with circulatory.
  3. Patients who were prescribed a diabetes medication had a 25.55% increase in the odds of readmission as compared to those without.

The odds ratio for numerical variables is the percentage increase (or decrease) in the odds of readmission for every unit increase (or decrease) in that variable. Therefore,

  1. Every additional hospital day increases the odds of a patient’s readmission by 1.8%.
  2. An increase in the number of procedures performed during a patient’s hospital stay reduces the odds of readmission by 4.29%.
  3. With every increase in the number of outpatient, inpatient, and emergency department visits prior to hospitalization, the odds of readmission rise by 46.79%, 12.85%, and 24.15%, respectively.

Recommendations

Using the odds ratios of the multivariate logistic model, the following groups should be the hospital’s focus for their follow up efforts to better monitor patients with high probability of readmission:

  1. Individuals that are at least 60 but below 90 years of age at the time of admission.
  2. Primarily diagnosed with diabetes or was prescribed a diabetes medication.
  3. With either of the following characteristics: long hospitalization time or frequently visited before hospital stay for all either types (outpatient, inpatient, and emergency room).

Nevertheless, it is also advised to explore for additional characteristics that can help better predict the probability of readmission among patients, as the data used may be insufficient to reliably identify patient groups with the best readmission rates.