Hospitals Cost & Quality Analysis

Author

Emma Wang

Picture: https://unsplash.com/photos

Dataset: https://corgis-edu.github.io/corgis/csv/hospitals/

Data Source: Medicare

Introduction

The data within the dataset was orginally sourced from Medicare, a federal health insurance program. It includes information regarding the performance data of hospitals across the country. The dataset holds 24 variables (19 categorical and 5 quantitative):

Facility.Name : the name of the hospital

Facility.City : city in which the hospital is located in

Facility.State : the state in which the hospital is based in

Facility.Type: the kind of organization operating the hospital (government, private, etc)

Rating.Overall: the overall rating of the hospital

Rating.Mortality : above, same, below, or unknown in comparison to the national hospital mortality rating

Rating.Safety : above, same, below, or unknown in comparison to the national hospital safety rating

Rating.Readmission : above, same, below, or unknown in comparison to national hospital readmission rating

Rating.Experience : above, same, below, or unknown in comparison to the national hospital patience experience rating

Rating.Effectiveness : above, same, below, or unknown in comparison to national hospital effectiveness of care

Rating.Timeliness : above, same, below, or unknown in comparison to national hospital timeliness of care

Rating.Imaging : above, same, below or unknown in comparison to national hospital effective use of imaging

Procedure.Heart Attack.Cost: the cost of care for heart attacks

Procedure.Heart Failure.Cost: the cost of care for heart failure

Procedure.Pneumonia.Cost: the cost of care for pneumonia

Procedure.Hip Knee.Cost: the cost of care for hip or knee issues

Procedure.Heart Attack.Quality: whether lower, average, worse in comparison to national quality rating

Procedure.Heart Failure.Quality: whether lower, average, worse in comparison to national quality rating

Procedure.Pneumonia.Quality: whether lower, average, worse in comparison to national quality rating

Procedure.Hip Knee Quality: whether lower, average, worse in comparison to national quality rating

Procedure.Heart Attack.Value : lower, average, worse, or unknown in comparison to national cost of care for heart failures

Procedure.Heart Failure.Value : lower, average, worse, or unknown in comparison to national cost of care for heart failures

Procedure.Pneumonia.Value : lower, average, worse, or unknown in comparison to the national cost of care for pneumonia

Procedure. Hip Knee.Value : lower, average, worse, or unknown in comparison to the national cost of care for hip or knee conditions

The dataset holds 4772 observations total.

I chose to analyze hospital type, quality, and cost as healthcare continues to become increasingly expensive in the US. Majority are aware of how much medical treatment can cost, and how it places a heavy burden to many individuals who require medical care but cannot afford the heightened costs. I believe that healthcare should be available to all individuals regardless of financial status. By evaluating hospital types, quality, and costs, I aim to identify affordable options for individuals running on strained budgets, and to see if higher costs guarantee improved treatment quality (if there is a correlation).

As previously stated, the dataset holds 24 variables total. However, I only need 7 of those variables, so I will begin by cleaning the data using the select() and rename() functions to make the data easier to work with.


Load Libraries

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.3     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)
library(ggplot2)
library(plotly)

Attaching package: 'plotly'

The following object is masked from 'package:ggplot2':

    last_plot

The following object is masked from 'package:stats':

    filter

The following object is masked from 'package:graphics':

    layout

Load the Dataset

hospitals = read_csv("~/Downloads/hospitals.csv")
Rows: 4772 Columns: 24
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (19): Facility.Name, Facility.City, Facility.State, Facility.Type, Ratin...
dbl  (5): Rating.Overall, Procedure.Heart Attack.Cost, Procedure.Heart Failu...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Exploring the Data

names(hospitals)
 [1] "Facility.Name"                   "Facility.City"                  
 [3] "Facility.State"                  "Facility.Type"                  
 [5] "Rating.Overall"                  "Rating.Mortality"               
 [7] "Rating.Safety"                   "Rating.Readmission"             
 [9] "Rating.Experience"               "Rating.Effectiveness"           
[11] "Rating.Timeliness"               "Rating.Imaging"                 
[13] "Procedure.Heart Attack.Cost"     "Procedure.Heart Attack.Quality" 
[15] "Procedure.Heart Attack.Value"    "Procedure.Heart Failure.Cost"   
[17] "Procedure.Heart Failure.Quality" "Procedure.Heart Failure.Value"  
[19] "Procedure.Pneumonia.Cost"        "Procedure.Pneumonia.Quality"    
[21] "Procedure.Pneumonia.Value"       "Procedure.Hip Knee.Cost"        
[23] "Procedure.Hip Knee.Quality"      "Procedure.Hip Knee.Value"       

Cleaning the Data

#clean the data by using select, and rename functions 
clean_hos = hospitals |> 
  #keeping the variables that I need
  select(Facility.Type, Rating.Overall, Rating.Effectiveness, ends_with("Cost")) |> 
  #renaming the variables so that they are easier to work with
  rename(
    heartattack_cost = `Procedure.Heart Attack.Cost`, 
    heartfailure_cost = `Procedure.Heart Failure.Cost`, 
    pneumonia_cost = `Procedure.Pneumonia.Cost`, 
    hipknee_cost = `Procedure.Hip Knee.Cost`
  )
head(clean_hos)
# A tibble: 6 × 7
  Facility.Type Rating.Overall Rating.Effectiveness heartattack_cost
  <chr>                  <dbl> <chr>                           <dbl>
1 Government                 2 Same                            23394
2 Government                 1 Above                           22579
3 Government                 3 Same                            24002
4 Private                    1 Below                               0
5 Proprietary                4 Same                                0
6 Private                    2 Below                           23940
# ℹ 3 more variables: heartfailure_cost <dbl>, pneumonia_cost <dbl>,
#   hipknee_cost <dbl>

Utilized the select() function to keep only the needed variables and rename() for simplicity.

clean_hos2 = clean_hos |>  
#create new column adding together treatment costs 
  mutate(
    hospital_cost = heartattack_cost + heartfailure_cost + hipknee_cost + pneumonia_cost
  ) |> 
#take out entries that resulted in 0, to only keep relevant entries 
  filter(hospital_cost > 0)

Mutated the data and created a new column “hospital_cost” by adding together the costs of the separate treatments. This allows us to look at each hospital’s overall pricing behavior.


Analyzing Hospital Type and Cost

#remove "Unknown" type entries from the subset 
type_hospital = clean_hos2 |> 
  filter(Facility.Type != "Unknown")

For the hospitals whose type wasn’t known, they were specified as “Unknown”. In order to ensure a clean and meaningful comparison across hospital types, I am excluding them.

ggplot(type_hospital, aes(x = Facility.Type, y = hospital_cost, fill = Facility.Type)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(
    title = "Comparing Hospital Types and Pricing Behavior", #visualization title
    subtitle = "Types: Government, Private, Proprietary, Church ",
    x = "Hospital Type", ,
    y = "Treatment Costs",
    caption = "Source: CORGIS, gathered from Medicare", 
    fill = "Hospital Type" #changing legend name 
  ) +
  scale_fill_manual(values = c("dodgerblue1", "hotpink2", "darkseagreen", "orchid4")) #manually assigning colors 

The visualization indicates that private hospitals exhibit significantly higher average treatment costs across hospital types. On the other hand, church-affiliated hospitals display the lowest average treatment costs, presenting an economical option for price-conscious patients.


Boxplot

#remove "None" entries for the hospitals with no data 
quality1 = clean_hos2 |> 
  filter(Rating.Effectiveness != "None")

Similar to how I removed the “Unknown” types for the prior visualization, I am removing the entries containing “None” for this boxplot. This allows us to only analyze relevant performance data.

#create a boxplot visualization displays the distribution of treatment costs by quality levels
p = ggplot(quality1, aes(x = Rating.Effectiveness, y = hospital_cost, fill = Rating.Effectiveness)) +
  geom_boxplot(alpha = 0.8) +
  theme_minimal() +
  labs(
    title = "Distribution of Treatment Costs Across Quality Level", 
    caption = "Source: CORGIS, gathered from Medicare", 
    x = "Quality Rating in Comparison to National Rating",
    y = "Average Hospital Cost",
    fill = "Quality Level"
  ) +
  scale_fill_manual(values = c("darkslategray3", "darkorange1", "indianred3"))

ggplotly(p) #make the boxplot visualization interactive

The boxplot reveals a paradoxical relationship between hospital costs and quality level. Hospitals providing “Above” average quality care had the highest median ($78K), however, the maximum cost distribution was actually lower than hospitals rated “Below” and “Same”. Both the “Below” and “Same” categories display wide spreads spanning from $10K - $100K in terms of treatment costs. This signifies that hospitals can charge inflated prices, while continuing to offer sub-par quality care. Ultimately, higher costs do not guarantee enhanced quality care, and there are options for patients with strained budgets to receive high grade quality treatments.


Multiple Linear Regression

When selecting the variables for this multiple linear regression model, I had two choices:

1) continuing the analysis on a macro scale (using hospital_cost and rating.overall)

2) shifting to a micro scale analysis by using the costs of each specific procedure (heart attack, heart failure, pneumonia, hip/knee)

I ultimately decided to continue the analysis on a macro scale so that the linear regression would directly align with my previous research and visualizations. I also integrated Facility.Type as a categorical control variable to allow the model to evaluate the relationship between treatment costs and quality ratings while keeping hospital type constant. Utilizing Facility.Type also smoothly connects back to the first visualization within this analysis.

fit1 = lm(Rating.Overall ~ hospital_cost + Facility.Type, data = clean_hos2)
summary(fit1)

Call:
lm(formula = Rating.Overall ~ hospital_cost + Facility.Type, 
    data = clean_hos2)

Residuals:
    Min      1Q  Median      3Q     Max 
-4.2047 -1.1292  0.2093  1.1957  3.5968 

Coefficients:
                           Estimate Std. Error t value Pr(>|t|)    
(Intercept)               1.625e+00  1.109e-01  14.651  < 2e-16 ***
hospital_cost             2.030e-05  1.009e-06  20.120  < 2e-16 ***
Facility.TypeGovernment  -4.995e-01  1.046e-01  -4.776 1.85e-06 ***
Facility.TypePrivate     -5.472e-02  9.494e-02  -0.576    0.564    
Facility.TypeProprietary -4.654e-01  1.057e-01  -4.402 1.10e-05 ***
Facility.TypeUnknown     -3.896e-02  1.150e-01  -0.339    0.735    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.55 on 4155 degrees of freedom
Multiple R-squared:  0.1227,    Adjusted R-squared:  0.1216 
F-statistic: 116.2 on 5 and 4155 DF,  p-value: < 2.2e-16

P-Value = 2.2e-16 <0.05

Adjusted R-Squared = .1216 (12.16%)

Equation: Y = 1.625 + 0.0000203 (hospital cost) - 0.4995 (government hospitals) - 0.0547 (private hospitals) - 0.4654 (proprietary hospitals)

^Note: Unknown hospitals were excluded since it’s p-value was higher than 0.05 | 0.735 > 0.05

The multiple linear regression model displays a statistically significant relationship between hospital pricing behavior and quality care levels. The model assigned church-affiliated hospitals as the baseline (intercept = 1.625). Previously, an analysis revealed that church-affiliated hospitals offered the lowest treatment expenditures across hospital types, proving them to be an appropriate baseline for this model.

A crucial observation involves private hospitals in particular. Private hospitals had a non-significant p-value of 0.564 relative to the baseline. Private hospitals were proved to mandate the highest treatment costs, however, this statistical indifference indicates that the inflated prices of private hospital treatments do not guarantee superior quality care.

The resulting p-value of 2.2e-16 is statistically significant as it sits substantially below the threshold of 0.05. However, this analysis deals with a massive amount of observations (N = 3718) essentially driving the p-value to be extremely small (as we saw here). Though there is a statistically significant result, it does not ensure real-world practical significance. To understand the real-world significance we can utilize the adjusted r-squared of 0.1216. This value indicates that hospital costs and types only account for 12.16% of variance in quality ratings. Ultimately, this low percentage reveals there is an extensive amount of factors involved when determining the quality of care hospitals provide.


Conclusion

Ultimately, through this analysis we evalutated:

  • Hospital Cost Across Hospital Types

  • Distribution of Treatment Costs Across Quality Levels

  • Multiple Linear Regression Model involving Hospital Costs, Types, and Overall Rating

The research and visualizations included within this analysis concludes that higher financial costs cannot guarantee improved quality care. These findings reinforce the belief that high quality care is able to be provided to all individuals without inflating costs and inflicting heavy financial burdens.


Technical Difficulties

The main technical challenge I faced was when turning the boxplot into an interactive visual. I was attempting to have the hospital name appear (in addition to the value) when you hover over the outliers. I tried incorporating “text = ..” into the aesthetics, however the names wouldn’t appear. I also turned to boxplot guides and even GitHub forums of people who had similar issues but I unfortunately was not able to get the code to work.

Sources:

GGPlot Color References:

https://sape.inf.usi.ch/quick-reference/ggplot2/colour

Boxplot Assistance:

https://ggplot2.tidyverse.org/reference/geom_boxplot.html