<jupyter_start><jupyter_text>Hospital Readmissions Data Analysis and Recommendations for Reduction BackgroundIn October 2012, the US government's Center for Medicare and Medicaid Services (CMS) began reducing Medicare payments for Inpatient Prospective Payment System hospitals with excess readmissions. Excess readmissions are measured by a ratio, by dividing a hospital’s number of “predicted” 30-day readmissions for heart attack, heart failure, and pneumonia by the number that would be “expected,” based on an average hospital with similar patients. A ratio greater than 1 indicates excess readmissions. GoalsIn this analysisI will:+ critique a preliminary analysis of readmissions data and recommendations (provided below) for reducing the readmissions rate+ construct a statistically sound analysis and make recommendations of your own  Resources+ Data source: https://data.medicare.gov/Hospital-Compare/Hospital-Readmission-Reduction/9n3s-kdb3+ More information: http://www.cms.gov/Medicare/medicare-fee-for-service-payment/acuteinpatientPPS/readmissions-reduction-program.html+ Markdown syntax: http://nestacms.com/docs/creating-content/markdown-cheat-sheet****<jupyter_code>%matplotlib inline

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import bokeh.plotting as bkp
from mpl_toolkits.axes_grid1 import make_axes_locatable
import seaborn as sns
import scipy as sp
# read in readmissions data provided
hospital_read_df = pd.read_csv('data/FY_2021_Hospital_Readmissions_Reduction_Program_Hospital.csv')<jupyter_output><empty_output><jupyter_text>**** Preliminary Analysis<jupyter_code># these are excluded from the analysis
hospital_read_df[hospital_read_df.loc[:, 'Number of Discharges'].isna()].shape
# deal with missing and inconvenient portions of data
clean_hospital_read_df = hospital_read_df[~hospital_read_df.loc[:, 'Number of Discharges'].isna()]
clean_hospital_read_df = clean_hospital_read_df[clean_hospital_read_df['Number of Discharges'] != 'Not Available']
clean_hospital_read_df = clean_hospital_read_df[~clean_hospital_read_df['Excess Readmission Ratio'].isna()]
# coerce to integer type
clean_hospital_read_df.loc[:, 'Number of Discharges'] = clean_hospital_read_df['Number of Discharges'].astype(int)
clean_hospital_read_df = clean_hospital_read_df.sort_values('Number of Discharges')
clean_hospital_read_df.shape
# generate a scatterplot for number of discharges vs. excess rate of readmissions
# lists work better with matplotlib scatterplot function
x = [a for a in clean_hospital_read_df['Number of Discharges'][81:-3]]
y = list(clean_hospital_read_df['Excess Readmission Ratio'][81:-3])

fig, ax = plt.subplots(figsize=(8,5))
ax.scatter(x, y,alpha=0.2)

ax.fill_between([0,350], 1.15, 2, facecolor='red', alpha = .15, interpolate=True)
ax.fill_between([800,2500], .5, .95, facecolor='green', alpha = .15, interpolate=True)

ax.set_xlim([0, max(x)])
ax.set_xlabel('Number of discharges', fontsize=12)
ax.set_ylabel('Excess rate of readmissions', fontsize=12)
ax.set_title('Scatterplot of number of discharges vs. excess rate of readmissions', fontsize=14)

ax.grid(True)
fig.tight_layout()<jupyter_output><empty_output><jupyter_text>**** Preliminary Report**A. Initial observations based on the plot above**+ Overall, rate of readmissions is trending down with increasing number of discharges+ With lower number of discharges, there is a greater incidence of excess rate of readmissions (area shaded red)+ With higher number of discharges, there is a greater incidence of lower rates of readmissions (area shaded green) **B. Statistics**+ In hospitals/facilities with number of discharges < 100, mean excess readmission rate is 1.023 and 68% have excess readmission rate greater than 1 + In hospitals/facilities with number of discharges > 1000, mean excess readmission rate is 0.978 and 45% have excess readmission rate greater than 1 **C. Conclusions**+ There is a significant correlation between hospital capacity (number of discharges) and readmission rates. + Smaller hospitals/facilities may be lacking necessary resources to ensure quality care and prevent complications that lead to readmissions.**D. Regulatory policy recommendations**+ Hospitals/facilties with small capacity (< 300) should be required to demonstrate upgraded resource allocation for quality care to continue operation.+ Directives and incentives should be provided for consolidation of hospitals and facilities to have a smaller number of them with higher capacity and number of discharges.<jupyter_code>x = pd.DataFrame(x)
y = pd.DataFrame(y)

df = pd.concat([x,y], axis=1)
df.columns = ['discharges', 'excess_readmissions']
df.tail()<jupyter_output><empty_output><jupyter_text>Overall, rate of readmissions is trending down with increasing number of discharges We can find this to be true because of the small p-value attached to the negative trendline. (99% confidence)<jupyter_code>sns.jointplot('discharges', 'excess_readmissions', data=df, kind='reg')<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>With lower number of discharges, there is a greater incidence of excess rate of readmissions (area shaded red) The p-value is a bit larger than 0.05; which is needed for 95% confidence. However, 0.09 is good enough for 90% confidence.<jupyter_code>red = df[df.discharges <= 350]
red = red[red['excess_readmissions'] >= 1.15]
red = red[red['excess_readmissions'] <= 2.00]
sns.jointplot('discharges', 'excess_readmissions', data=red, kind='reg', color="r")<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>With higher number of discharges, there is a greater incidence of lower rates of readmissions (area shaded green) We can find this to be true because of the small p-value attached to the negative trendline. (99% confidence)<jupyter_code>green = df[df.discharges >= 800]
green = green[green.discharges <= 2500]
green = green[green['excess_readmissions'] >= 0.50]
green = green[green['excess_readmissions'] <= 0.95]
sns.jointplot('discharges', 'excess_readmissions', data=green, kind='reg', color="g")<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>In hospitals/facilities with number of discharges < 100, mean excess readmission rate is 1.023 and 69% have excess readmission rate greater than 1<jupyter_code>lo_df = df[df.discharges < 100]
lo_discharges, lo_excess_readmissions = lo_df.mean()
lo_greater_than_one = len(lo_df[lo_df.excess_readmissions > 1]) / len(lo_df)

print('Excess readmission rate :', '%.3f' % lo_excess_readmissions)
print('%.2f' % lo_greater_than_one, 'have excess readmission rate greater than 1.')
sns.jointplot('discharges', 'excess_readmissions', data=lo_df, kind='reg')<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>In hospitals/facilities with number of discharges > 1000, mean excess readmission rate is 0.978 and 45% have excess readmission rate greater than 1  NOTE: Although this is true, there is no trend that says excess readmission rates decrease . See joint plot for more info. (p=0.65) Thus, this statistic could be misleading.<jupyter_code>hi_df = df[df.discharges > 1000]
hi_discharges, hi_excess_readmissions = hi_df.mean()
hi_greater_than_one = len(hi_df[hi_df.excess_readmissions > 1]) / len(hi_df)

print('Excess readmission rate :', '%.3f' % hi_excess_readmissions)
print('%.2f' % hi_greater_than_one, 'have excess readmission rate greater than 1.')
sns.jointplot('discharges', 'excess_readmissions', data=hi_df, kind='reg')<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>There is a significant correlation between hospital capacity (number of discharges) and readmission rates. (99% confidence) This conclusion follows our first observation.<jupyter_code>sns.jointplot('discharges', 'excess_readmissions', data=df, kind='reg')<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Smaller hospitals/facilities may be lacking necessary resources to ensure quality care and prevent complications that lead to readmissions. According to the data, this a reasonable. However, there may be other factors such as insurance and doctor ratings not available in the data.  Hospitals/facilties with small capacity (< 300) should be required to demonstrate upgraded resource allocation for quality care to continue operation. This is a bold recommendation. We need to see the pros and cons of introducing upgraded resource allocation.Pros+ Save patient time+ Increase space for new patients+ Secure government fundingCons+ Less readmissions could result in less income+ Low income could lead to shut down of smaller hospitalsIf trying to meet regulatory policies, then smaller hospitals should be required to demonstrate upgraded resource allocation. However, at a business perspective, they should be reccomended to do so only if it is beneficial for the hospital itself.<jupyter_code>lo_df = df[df.discharges < 300]
lo_discharges, lo_excess_readmissions = lo_df.mean()
lo_greater_than_one = len(lo_df[lo_df.excess_readmissions > 1]) / len(lo_df)

print('Excess readmission rate :', '%.3f' % lo_excess_readmissions)
print('%.2f' % lo_greater_than_one, 'have excess readmission rate greater than 1.')
sns.jointplot('discharges', 'excess_readmissions', data=lo_df, kind='reg')<jupyter_output>/Users/sarahluw/.pyenv/versions/3.6.2/envs/my-virtual-env-3.6.2/lib/python3.6/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning<jupyter_text>Directives and incentives should be provided for consolidation of hospitals and facilities to have a smaller number of them with higher capacity and number of discharges. Following the previous logic, this could benefit patient or the hospital. The directives and incentives should vary due to different circumstances. For example, larger hospitals with more flexible budgets could focus on less excess readmission. Smaller hospitals could be encouraged to consolidate if it could benefit them over simply reallocating resources.  New Hypothesis Testing Our new hypothesis is going to be: There is a significant difference between excess readmission rates for different states.<jupyter_code># Making a new dataframe with state variables 

x = list(clean_hospital_read_df['State'][81:-3])
y = list(clean_hospital_read_df['Excess Readmission Ratio'][81:-3])

x = pd.DataFrame(x)
y = pd.DataFrame(y)

df = pd.concat([x,y], axis=1)
df.columns = ['state', 'excess_readmissions']
df = df.groupby('state').mean().reset_index()
df.head()
# Filtering the top and bottom 10 states with excess readmission rates.

lo_excess = df.sort_values(by='excess_readmissions').head(10)
hi_excess = df.sort_values(by='excess_readmissions').tail(10)<jupyter_output><empty_output><jupyter_text>Here we have the bar plot for the top 10 and bottom 10 states with excess readmission rates. To test for significant difference, we are going to test SD (South Dakota) and DC (District of Columbia). We picked these two because SD had the lowest excess readmission rate and DC had the highest.<jupyter_code>sns.barplot('state', 'excess_readmissions', data=lo_excess)
plt.title('Top 10 states with low excess readmission rates')
sns.barplot('state', 'excess_readmissions', data=hi_excess)
plt.title('Top 10 states with high excess readmission rates')
## Going back to original dataframe

x = list(clean_hospital_read_df['State'][81:-3])
y = list(clean_hospital_read_df['Excess Readmission Ratio'][81:-3])

x = pd.DataFrame(x)
y = pd.DataFrame(y)

df = pd.concat([x,y], axis=1)
df.columns = ['state', 'excess_readmissions']
df.tail()
# Data for SD (South Dakota)

sd = df[df.state == 'SD']
sd = sd['excess_readmissions']
sd.describe()
# Data for CT (Connecticut)

ct = df[df.state == 'CT']
ct = ct['excess_readmissions']
ct.describe()<jupyter_output><empty_output><jupyter_text>Here we have an very small p-value, enough for 99% confidence.<jupyter_code># T-test between SD and DC

sp.stats.ttest_ind(sd, ct)
# Visualizing conclusion with violin plot

sd = df[df.state == 'SD']
sd = sd[['excess_readmissions']]
sd.columns = ['South Dakota Excess Readmission Rate']

ct = df[df.state == 'CT']
ct = ct[['excess_readmissions']]
ct.columns = ['Connecticut Excess Readmission Rate']

fig, axs = plt.subplots(ncols=2, sharey=True)
sns.violinplot(data=sd, ax=axs[0], color='#9b59b6')
sns.violinplot(data=ct, ax=axs[1], color='#3498db')<jupyter_output><empty_output><jupyter_text>Conclusion There is a significant difference between excess readmission rates for different states. (99% confidence)  Is there a significant relationship between discharges and excess readmission ratio?<jupyter_code>import statsmodels.api as sm
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import scale

X = scale(clean_hospital_read_df["Number of Discharges"])
y = clean_hospital_read_df["Excess Readmission Ratio"]

X = sm.add_constant(X) 
model = sm.OLS(y, X).fit()
model.summary()<jupyter_output><empty_output><jupyter_text>Is there more to the story?We should also consider type of readmission. Smaller hospitals seem similar to large hospitals in all readmission types except hip-knee. In fact, most of the difference we see in overall readmission rates between small and large hospitals may be due to hip-knee.<jupyter_code>clean_hospital_read_df['Measure Name'].unique()
from scipy import stats

def assign_size_1(x):
    if x> 1000:
        size = 3
    elif x > 300:
        size = 2
    else:
        size = 1
    return size

def assign_size_2(x):
    if x> 1000:
        size = 3
    elif x > 100:
        size = 2
    else:
        size = 1
    return size

clean_hospital_read_df['size_1'] = clean_hospital_read_df['Number of Discharges'].apply(assign_size_1)
clean_hospital_read_df['size_2'] = clean_hospital_read_df['Number of Discharges'].apply(assign_size_2)

for i in clean_hospital_read_df['Measure Name'].unique():
    mask1 = (clean_hospital_read_df['size_1'] == 1) & (clean_hospital_read_df['Measure Name'] == i)
    mask2 = (clean_hospital_read_df['size_1'] == 3) & (clean_hospital_read_df['Measure Name'] == i)
    
    ratio_small = clean_hospital_read_df.loc[mask1, 'Excess Readmission Ratio']
    ratio_large = clean_hospital_read_df.loc[mask2, 'Excess Readmission Ratio']
    print('ratio difference:', ratio_small.mean() / ratio_large.mean())
    print(stats.ttest_ind(ratio_small, ratio_large, equal_var = False))
    
    sns.kdeplot(clean_hospital_read_df.loc[mask1, 'Excess Readmission Ratio'], label = '<300 discharges')
    sns.kdeplot(clean_hospital_read_df.loc[mask2, 'Excess Readmission Ratio'], label = '>1000 discharges')
    
    plt.title('%s: \nDifferences in Admission Ratio' %i, fontsize=14)

    plt.show()<jupyter_output>ratio difference: 1.0788603917403392
Ttest_indResult(statistic=4.999344040795371, pvalue=8.367747764026845e-05)
{'fraction_non_alphanumeric': 0.09512624779800352, 'fraction_numerical': 0.023253082795067527, 'mean_word_length': 5.959950960359624, 'pattern_counts': {'":': 0, '<': 64, '<?xml version=': 0, '>': 67, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '474659', 'license': 'MIT', 'n_tokens_mistral': 5487, 'n_tokens_neox': 5030, 'n_words': 1703, 'path': '01222022_eda/hospital_readmissions_fy21_eda_01222022.ipynb', 'repo_name': 'saran-ahluwalia/cms_ideas_fy_2022', 'size': '17030'}