Main

Row

Sample Size: All

4784

Percent Reorting: All

Sample Size: HRRP

3291

Percent Reorting: HRRP

Sample Size: Exempt

1493

Percent Reorting: Exempt

Row

Readmission Ratio Violin Plots

Mean Readmission Ratio Bar Plots

Row

HRRP Readmissions Ratio Map

National Comparison Mosaic Plot

Data

HRRP Data

Documentation

Background

The Hospital Readmissions Reduction Program (HRRP) aims to reduce patient readmissions by reducing payments disbursed to hospitals with excessive readmissions that occur within 30 days of the initial visit. Payments can be reduced upto a cap of 3% for any Fee-For-Service hospital. The program tracks six specific conditions:

The General Hospital Information (GHI) dataset comes from an additional dataset available. on Medicare’s open data portal. It includes data on hospital features such as type of ownership (e.g., government, private, non-profit), hospital type (e.g., children’s hospital, acute care hospital, etc.), and comparisons to national averages of ratings across various dimensions such as patient experience.

Calculating Readmission Ratios

Excess readmissions are measured with a ratio for each type of condition. The ratio is calculated by dividing the number of “predicted” 30-day readmissions for a hospital for the given condition by the number that is “expected” for the same hospital and condition.

\[Readmission\:Ratio=\frac{Predicted\:Readmissions}{Expected\:Readmissions}\]

Total “predicted” 30-day readmissions is the number of readmissions that would be anticipated in a particular hospital adjusted for risk using the demographics of the area covered by the hospital. Total “expected” 30-day readmissions is the number of readmissions that would be expected if the same patients had been treated at an “average” hospital.

Resources

Description of the HRRP from the Centers for Medicare & Medicaid Services — https://www.cms.gov/Medicare/Medicare-Fee-for-Service-Payment/AcuteInpatientPPS/Readmissions-Reduction-Program.html

HRRP Data — https://data.medicare.gov/Hospital-Compare/Hospital-Readmissions-Reduction-Program/9n3s-kdb3

General Hospital Information Data — https://data.medicare.gov/Hospital-Compare/Hospital-General-Information/xubh-q36u

Description of computation methods from the Agency for Healthcare Research and Quality — https://www.ahrq.gov/professionals/systems/hospital/red/toolkit/redtool-30day.html

---
title: "Hospital Readmission Reduction Program Analysis Dashboard"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: scroll
    source_code: embed
    navbar:
      - {title: "Arcenis Rojas", 
      href: "https://arcenis-r.github.io/ajr-portfolio/"}
      - {icon: "fa fa-github fa-lg",
      href: "https://github.com/arcenis-r"}
      - {icon: "fa fa-linkedin fa-lg",
      href: "https://linkedin.com/in/arcenisrojas"}
---

```{r setup, include=FALSE}
library(leaflet)
library(plotly)
library(ggmosaic)
library(tidyverse)
library(flexdashboard)

# Write a function to generate gauges for percentages
my_gauge <- function(x) {
  gauge(
    value = x, min = 0, max = 100,
    sectors = gaugeSectors(
      success = c(80, 100), warning = c(50, 79.99), danger = c(0, 49.99),
      colors = c("green", "yellow", "red")
    ),
    symbol = "%"
  )
}

# Read in hospital data
hosp_data <- RSocrata::read.socrata(
  "https://data.medicare.gov/resource/rbry-mqwu.json"
) %>%
  
  # Keep only the necessary variables
  select(
    provider_id, state, hospital_name, hospital_overall_rating, hospital_type,
    location.coordinates, ends_with("national_comparison")
  ) %>%
  
  # Clean up the variable names
  set_names(
    names(.) %>% str_replace_all("hospital_", "") %>% 
      str_replace_all("_national_comparison", "")
  ) %>%
  
  dplyr::rename(
    timeliness = "timeliness_of_care", 
    effectiveness = "effectiveness_of_care",
    imaging = "efficient_use_of_medical_imaging",
    experience = "patient_experience",
    safety = "safety_of_care"
  ) %>%
  
  # Replace all the values of "Not Available" with NA
  mutate_all(
    funs(replace(., . == "Not Available", NA_character_))
  ) %>%
  
  # Covert all categorical variables to factor
  mutate_at(
    vars(effectiveness:timeliness), 
    funs(
      str_to_title(.) %>%
      fct_relevel(
        "Above The National Average", "Same As The National Average",
        "Below The National Average"
      )
    )
  ) %>% 
  
  # Reorder the overall rating variable from 1 to 5 and create a status variable
  # indicating whether a hospital is monitored by the HRRP
  mutate(
    overall_rating = as.character(overall_rating) %>% 
      fct_relevel(as.character(1:5)),
    status = ifelse(
      str_detect(type, "^Acute") & !state == "MD", "HRRP", "Exempt")
  )

# Unlist the location data
hosp_data <- hosp_data %>%
  left_join(
    hosp_data %>% select(provider_id, location.coordinates) %>%
      drop_na(location.coordinates) %>%
      mutate(
        long = flatten_dbl(
          map(location.coordinates, ~ ifelse(!is.null(.x), .x[1], .x))
        ), 
        lat = flatten_dbl(
          map(location.coordinates, ~ ifelse(!is.null(.x), .x[2], .x))
        )
      ) %>%
      select(-location.coordinates),
    by = "provider_id"
  ) %>%
  select(-location.coordinates)


# Read in the program data
prog_data <- RSocrata::read.socrata(
  "https://data.medicare.gov/resource/kac9-a9fp.json"
) %>%
  
  # Keep only necessary variables
  select(provider_id, measure_id, readm_ratio) %>%
  
  # Keep only the important parts of the measure ID label names and convert it
  # to a factor variable and convert the readmission ratio data to numeric
  mutate(
    measure_id = str_replace_all(measure_id, "^READM-30-", "") %>%
      str_replace_all("-HRRP", "") %>% as_factor,
    readm_ratio = as.numeric(readm_ratio)
  )

# Merge the data
hrrp_data <- hosp_data %>%
  left_join(
    prog_data %>%
      
      # Spread the column with the conditions across multiple columns using the
      # readmission ratio as the values
      spread(measure_id, readm_ratio) %>%
      
      # Create a variable indicating whether the given hospital has readmissions
      # rate data
      mutate(
        rprt = select(., -provider_id) %>% 
          apply(1, function(x) as.numeric(sum(!is.na(x)) > 0)),
        mn_rr = rowMeans(select(., -provider_id, -rprt), na.rm = TRUE)
      ),
    by = "provider_id"
  )

geo_data <- hrrp_data %>%
  filter(status %in% "HRRP") %>%
  select(long, lat, readm_ratio = "mn_rr", name) %>%
  drop_na()

cols <- colorQuantile(c("blue", "gray", "red"), geo_data$readm_ratio, n = 5)

geo_data <- sp::SpatialPointsDataFrame(
  geo_data %>% select(long, lat), 
  geo_data %>% select(-c(long, lat))
)
```

Main
================================================================================

Row {data-height=150}
--------------------------------------------------------------------------------

```{r gen_counts, echo=FALSE, include=FALSE}
# Generate sample counts, counts of hospitals reporting, total readmissions per
# hospital, and percent reporting
counts <- hrrp_data %>%
  group_by(status) %>%
  summarise(
    count = n(),
    rprt_count = sum(rprt, na.rm = T), 
    mean_rr = mean(mn_rr, na.rm = T)
  ) %>%
  bind_rows(
    hrrp_data %>%
      summarise(
        count = n(),
        rprt_count = sum(rprt, na.rm = T), 
        mean_rr = mean(mn_rr, na.rm = T)
      ) %>%
      mutate(status = "All")
  ) %>%
  ungroup %>%
  mutate(pct_rprt = scales::percent(rprt_count / count))
```

### Sample Size: All
```{r sample_all}
valueBox(counts %>% filter(status == "All") %>% pull(count))
```


### Percent Reorting: All
```{r pct_rprt_all}
my_gauge(counts %>% filter(status == "All") %>% pull(pct_rprt))
```

### Sample Size: HRRP
```{r sample_hrrp}
valueBox(counts %>% filter(status == "HRRP") %>% pull(count))
```


### Percent Reorting: HRRP
```{r pct_rprt_hrrp}
my_gauge(counts %>% filter(status == "HRRP") %>% pull(pct_rprt))
```

### Sample Size: Exempt
```{r sample_exempt}
valueBox(counts %>% filter(status == "Exempt") %>% pull(count))
```


### Percent Reorting: Exempt
```{r pct_rprt_exempt}
my_gauge(counts %>% filter(status == "Exempt") %>% pull(pct_rprt))
```


Row {data-height=425; .tabset}
--------------------------------------------------------------------------------
### Readmission Ratio Violin Plots
```{r violin_plots}
v <- hosp_data %>%
  left_join(prog_data, by = "provider_id") %>%
  drop_na(measure_id, readm_ratio) %>%
  ggplot(aes(x = measure_id, y = readm_ratio, fill = measure_id)) +
  geom_violin() +
  facet_wrap(~ status) +
  theme_light() +
  theme(plot.title = element_text(hjust = 0.5), legend.position = "none") +
  labs(
    x = "Condition", y = "Readmission Ratio",
    title = "Readmission Ratio Distribution by Condition and Program Status"
  )

ggplotly(v)
```

### Mean Readmission Ratio Bar Plots
```{r bar_plots}
b <- hosp_data %>%
  left_join(prog_data, by = "provider_id") %>%
  drop_na(measure_id, readm_ratio) %>%
  group_by(status, measure_id) %>%
  summarise(readm_ratio = mean(readm_ratio)) %>%
  ungroup %>%
  ggplot(aes(x = measure_id, y = readm_ratio, fill = measure_id)) +
  geom_bar(stat = "identity") + 
  facet_wrap(~ status) +
  theme_light() +
  theme(plot.title = element_text(hjust = 0.5), legend.position = "none") +
  labs(
    y = "Mean Radmission Ratio", x = "Condition",
    title = "Mean Readmission Ratio by Condition and Program Status"
  ) +
  scale_y_continuous(limits = c(0.95, 1.05), oob = scales::rescale_none)

ggplotly(b)
```


Row {data-height=425}
--------------------------------------------------------------------------------

### HRRP Readmissions Ratio Map
```{r}
# Generate the map
leaflet(data = geo_data) %>%
  addTiles() %>%
  
  # Set the center of the map and the zoom level
  setView(
    lng = ((max(geo_data$long) - min(geo_data$long)) / 2) + min(geo_data$long),
    lat = ((max(geo_data$lat) - min(geo_data$lat)) / 2) + min(geo_data$lat),
    zoom = 2.45
  ) %>%
  
  # Add the markers colored based on whether the given hospital ratio's was high
  # or low and add a label that shows the hospital name and its readmission
  # ratio
  addCircleMarkers(
    radius = 1,
    color = ~cols(readm_ratio),
    opacity = 0.8,
    label = ~paste(name, "-", readm_ratio)
  ) %>%
  addLegend(
    "bottomright", pal = cols, values = ~readm_ratio,
    title = "Readmissions Ratio Quintile", opacity = 1
  )
```


### National Comparison Mosaic Plot
```{r}
p <- hrrp_data %>%
  mutate(
    readmission = str_replace_all(readmission, " The National Average", "") %>%
      str_replace_all(" As", "") %>%
      fct_relevel("Below", "Same", "Above")
  ) %>%
  ggplot() +
  geom_mosaic(
    aes(
      x = product(readmission, overall_rating), 
      fill = readmission, 
      conds = product(status)
    ),
    na.rm = TRUE
  ) +
  coord_flip() +
  labs(
    x = "Readmissions Rating vs National Avg. by Status",
    y = "Overall Rating",
    title = str_wrap(
      "Readmissions Rating vs National Avg. by Overall Rating by Status",
      40
    )
  ) +
  guides(fill = guide_legend(reverse = TRUE)) +
  theme_light() +
  theme(
    panel.grid = element_blank(),
    panel.border = element_blank(),
    legend.title = element_blank(),
    plot.title = element_text(hjust = 0.5)
  ) +
  scale_fill_brewer(palette = "Set1")

ggplotly(p) %>%
  add_annotations(
    text = str_wrap("Comparison Values", 10),
    xref = "paper", yref = "paper",
    x = 1.02, xanchor = "left",
    y = 0.6, yanchor = "bottom",    # Same y as legend below
    legendtitle = TRUE, showarrow = FALSE
  ) %>%
  layout(legend = list(y = 0.6, yanchor = "top"))
```


Data
================================================================================

### HRRP Data
```{r hrrp_table}
DT::datatable(
  hrrp_data %>% 
    select(name, state, status, mn_rr) %>%
    mutate(mn_rr = round(mn_rr, 3)) %>%
    set_names(
      c("Hospital Name", "State", "HRRP Status", "Mean Readmission Ratio")
    ), 
  options = list(pageLength = 25, scrollX = TRUE)
)
```


Documentation {data-orientation=rows}
================================================================================

**Background**

The Hospital Readmissions Reduction Program (HRRP) aims to reduce patient readmissions by reducing payments disbursed to hospitals with excessive readmissions that occur within 30 days of the initial visit. Payments can be reduced upto a cap of 3% for any Fee-For-Service hospital. The program tracks six specific conditions:

- Acute Myocardial Infarction (AMI)
- Chronic Obstructive Pulmonary Disease (COPD)
- Heart Failure (HF)
- Pneumonia
- Coronary Artery Bypass Graft (CABG) Surgery
- Elective Primary Total Hip Arthroplasty and/or Total Knee Arthroplasty (THA/TKA)

The General Hospital Information (GHI) dataset comes from an additional dataset available. on Medicare's open data portal. It includes data on hospital features such as type of ownership (e.g., government, private, non-profit), hospital type (e.g., children's hospital, acute care hospital, etc.), and comparisons to national averages of ratings across various dimensions such as patient experience.


**Calculating Readmission Ratios**

Excess readmissions are measured with a ratio for each type of condition. The ratio is calculated by dividing the number of "predicted" 30-day readmissions for a hospital for the given condition by the number that is "expected" for the same hospital and condition.

$$Readmission\:Ratio=\frac{Predicted\:Readmissions}{Expected\:Readmissions}$$

Total "predicted" 30-day readmissions is the number of readmissions that would be anticipated in a particular hospital adjusted for risk using the demographics of the area covered by the hospital. Total "expected" 30-day readmissions is the number of readmissions that would be expected if the same patients had been treated at an "average" hospital.


**Resources**

Description of the HRRP from the Centers for Medicare & Medicaid Services ---

https://www.cms.gov/Medicare/Medicare-Fee-for-Service-Payment/AcuteInpatientPPS/Readmissions-Reduction-Program.html

HRRP Data --- 
https://data.medicare.gov/Hospital-Compare/Hospital-Readmissions-Reduction-Program/9n3s-kdb3

General Hospital Information Data --- 
https://data.medicare.gov/Hospital-Compare/Hospital-General-Information/xubh-q36u 

Description of computation methods from the Agency for Healthcare Research and Quality --- 
https://www.ahrq.gov/professionals/systems/hospital/red/toolkit/redtool-30day.html