<jupyter_start><jupyter_text>Columns:- `age` in years- `sex` (1 = male; 0 = female)- `cp` chest pain type- `trestbps` resting blood pressure (in mm Hg on admission to the hospital)- `chol` serum cholestoral in mg/dl- `fbs` (fasting blood sugar > 120 mg/dl) (1 = true; 0 = false)- `restecg` resting electrocardiographic results- `thalach` maximum heart rate achieved- `exang` exercise induced angina (1 = yes; 0 = no)- `oldpeak` ST depression induced by exercise relative to rest- `slope` the slope of the peak exercise ST segment- `ca` number of major vessels (0-3) colored by flourosopy- `thal` 3 = normal; 6 = fixed defect; 7 = reversable defect- `target` 1 or 0 (I think this means 1= heart attack; 0=no heart attack)  Inspect.- Check for datatypes (make sure that there are no strings).- Check for null values.- Check size of df.<jupyter_code># Check size of dataframe.
n_rows = df.shape[0]
n_columns = df.shape[1]
print (f"Number of rows: {n_rows}")
print (f"Number of columns: {n_columns}")
# Inspect datatypes.
df.dtypes
# Check out description.
df.describe()
# Check out if there are any null values.
df.isnull().sum()
# Columns being used for X_train/X_test
columns_list = df.columns.tolist()[:13]
columns_list<jupyter_output><empty_output><jupyter_text>Summary of data:    - No missing data    - No categorical data  Visualize.<jupyter_code>df.hist(figsize=(10,10));
# Heatmap of the data to look for correlations.
plt.figure(figsize=(10, 10))
sns.heatmap(df.corr(), annot=True, square=True);<jupyter_output><empty_output><jupyter_text>Age as an indicator for heart disease.<jupyter_code># Graph age v. heart disease incidence.
sns.countplot(x="age", data=df, hue="target");
plt.xticks(rotation=90);
plt.legend(loc="upper right");
plt.title("Age");<jupyter_output><empty_output><jupyter_text>This plot considers age and its role as an indicator for heart attack.  The legend indicates heart attack (1) v. no heart attack (0).  In this case, the graph indicates that there is little to correlation of age as an indicator for heart attack.  This is further evidenced by the heat map having a negative correlation value of -0.23.  Gender as an indicator for heart disease.<jupyter_code># Graph gender v. heart disease incidence.
sns.countplot(x="sex", data=df, hue="target");
plt.xticks(rotation=90);
plt.legend(loc="upper right");
plt.title("Sex");
# Check out the ratio of females to males.
df["sex"].value_counts()/len(df)<jupyter_output><empty_output><jupyter_text>This plot considers sex and its role as an indicator for heart attack.  First, it appears that the data is skewed to males, meaning, that there are more males in this study compared to females.  In fact, the ratio of males to females is 2:1.  Second, the female population has a higher rate of heart attacks; the male population has a lower rate of heart attacks.  Due to this discrepancy, the heatmap reads this as not having a positive correlation.  In other words, heatmap is indicating that sex is not an indicator of having a heart attack (-0.28).  Chest pain as an indicator for heart disease.<jupyter_code># Graph chest pain v. heart disease incidence.
sns.countplot(x="cp", data=df, hue="target");
plt.xticks(rotation=90);
plt.legend(loc="upper right");
plt.title("Chest Pain Type");
# If you're having chest pains (cp>=1) what is ratio of having a heart attack(1)?
holder = df.groupby(["cp", "target"]).count()["age"]

# Find total number of cp with target=1.
total = 0
for i in range(1, 4):
    for j in range(1, 2):
        want = holder[i, j]
        total += want
        
cp_0_t1 = holder[0, 1]
cp_0_t0 = holder[0, 0]

print (f"Number of cp with heart attacks: {total}")
print (f"Ratio of cp with heart attacks to no heart attacks: {total/(holder.sum() - cp_0_t1 - cp_0_t0)}")<jupyter_output>Number of cp with heart attacks: 126
Ratio of cp with heart attacks to no heart attacks: 0.7875<jupyter_text>This plot considers chest pain type as an indicator for heart attack.  For data where cp is 1 or higher, the incidence of heart attack is high.  For data were cp is 0, the value of 0 indicates that there is no chest pain and correlates strongly with the absence of heart attack.  According to the heatmap, the value for cp is 0.43, a positive correlation.  That means that cp is an indicator of having a heart attack. Summary of Visualizations:    - Considering the various columns in reference to `target`, there are a few positive and negative relationships.        * notable positive relationships include: cp, thalach, and slope.        * notable negative relationships include: age, sex, exang, oldpeak, ca, and thal.  Models!<jupyter_code># Consolidate the split of data.
def data_split(df, ts, rs):
    '''
    INPUT
    - df (dataframe)
    - ts = test_size
    - rs = random_state
    
    OUTPUT
    - X_train, X_test, y_train, y_test
    
    This function does the following:
    1. Split df into X and y.
    2. Split into train and test sets (test_size=0.33, random_state=42)
    '''
    # Split the data for X and y.
    y = df["target"]
    X = df.drop("target", axis=1)
    
    # Split data into test and train.
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=ts, random_state=rs)
    
    return X_train, X_test, y_train, y_test<jupyter_output><empty_output><jupyter_text>Linear Regression.<jupyter_code># Try a linear regression model.
def linear_reg(df):
    '''
    INPUT
    - df (dataframe)
    
    OUTPUT
    - r2_scores_test, r2_scores_train
    
    This function does the following:
    1. Grab the split data using data_split.
    2. Fit the Linear Regression model with normalization.
    3. Run prediction.
    4. Find r2_scores for test and train to determine if overfitting.
    '''
    # Grab data.
    X_train, X_test, y_train, y_test = data_split(df, 0.33, 42)
    
    # Fit the Linear Regression model.
    model = LinearRegression(normalize=True)
    model.fit(X_train, y_train)
    
    # Prediction.
    prediction_train = model.predict(X_train)
    prediction_test = model.predict(X_test)
    
    # Find r2_scores for test and train.
    r2_scores_train = r2_score(y_train, prediction_train)
    r2_scores_test = r2_score(y_test, prediction_test)
    
    return r2_scores_train, r2_scores_test
# Run Linear Regression.
linear_reg(df)<jupyter_output><empty_output><jupyter_text>Linear regression doesn't seem like a good model for this.  The train numbers aren't so good.  Try another model type.  Logistic Regression.<jupyter_code># Try logistic regression with scaled data.
def logistic_reg_scale(df):
    '''
    INPUT
    - df (dataframe)
    
    OUTPUT
    - accuracy_train, accuracy_test
    
    This function does the following:
    1. Grab the split data using data_split.
    3. Scale the data.
    4. Fit the Logistic Regression model with normalization.
    5. Run prediction.
    6. Find r2_scores for test and train to determine if overfitting.
    '''
    # Split data into test and train.
    X_train, X_test, y_train, y_test = data_split(df, 0.2, 42)
    
    # Scale the data.
    scale = StandardScaler()
    X_train_scale = scale.fit_transform(X_train)
    X_train = pd.DataFrame(X_train_scale)
    X_test_scale = scale.fit_transform(X_test)
    X_test = pd.DataFrame(X_test_scale)
    
    # Fit the Logistic Regression model.
    model = LogisticRegression()
    model.fit(X_train, y_train)
    
    # Prediction.
    prediction_train = model.predict(X_train)
    prediction_test = model.predict(X_test)
    
    # Find r2_scores for test and train.
    accuracy_train = accuracy_score(y_train, prediction_train)
    accuracy_test = accuracy_score(y_test, prediction_test)
    
    a = f"Train \n {classification_report(y_train, prediction_train)}"
    b = f"Test \n {classification_report(y_test, prediction_test)}"
    return a, b, accuracy_train, accuracy_test, X_train, y_train, model, X_test, y_test
# The output keys need to be changed to a string.  
columns_dict = {}
for x in range(13):
    columns_dict[x] = columns_list[x]
columns_dict
# Run Logistic Regression on data.
a, b, accuracy_train, accuracy_test, X_train, y_train, model, X_test, y_test = logistic_reg_scale(df)
X_train = X_train.rename(columns=columns_dict)

# Print some outputs (accuracy, classification report).
print (accuracy_train)
print (accuracy_test)
print (" ")
print (a)
print (b)

# Find ranked features.
perm = PermutationImportance(model).fit(X_train, y_train)
thing1 = eli5.show_weights(perm, feature_names = X_train.columns.tolist())
thing1
# Graph the ROC
# calculate the fpr and tpr for all thresholds of the classification
probs = model.predict_proba(X_test)
preds = probs[:,1]
fpr, tpr, threshold = metrics.roc_curve(y_test, preds)
roc_auc = metrics.auc(fpr, tpr)

import matplotlib.pyplot as plt
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()<jupyter_output><empty_output><jupyter_text>SVC.<jupyter_code># Try SVC.
def svc_model(df):
    '''
    INPUT
    - df (dataframe)
    
    OUTPUT
    - classification report train, classification report test, accuracy_train, 
      accuracy_test, X_train, y_train, model, X_test, y_test
    
    This function does the following:
    1. Grab the split data using data_split.
    2. Scale the data.
    3. Fit the SVC model with normalization.
    4. Run prediction.
    5. Do classification report, accuracy for test and train to determine if overfitting.
    '''
    # Grab the data.
    X_train, X_test, y_train, y_test = data_split(df, 0.2, 42)
    
    # Fit the SVC model.
    model = SVC(probability=True, kernel="linear", C=0.15)
    model.fit(X_train, y_train)
    
    # Prediction.
    prediction_train = model.predict(X_train)
    prediction_test = model.predict(X_test)
    
    # Find accuracy_scores for test and train.
    accuracy_train = accuracy_score(y_train, prediction_train)
    accuracy_test = accuracy_score(y_test, prediction_test)
    
    a = f"Train \n {classification_report(y_train, prediction_train)}"
    b = f"Test \n {classification_report(y_test, prediction_test)}"
    return a, b, accuracy_train, accuracy_test, X_train, y_train, model, X_test, y_test
# Run SVC on data.
a, b, accuracy_train, accuracy_test, X_train, y_train, model, X_test, y_test = svc_model(df)

# Print some outputs (accuracy, classification report).
print (accuracy_train)
print (accuracy_test)
print (" ")
print (a)
print (b)

# Find ranked features.
perm = PermutationImportance(model).fit(X_train, y_train)
thing2 = eli5.show_weights(perm, feature_names = X_train.columns.tolist())
thing2
# Graph the ROC
# calculate the fpr and tpr for all thresholds of the classification
probs = model.predict_proba(X_test)
preds = probs[:,1]
fpr, tpr, threshold = metrics.roc_curve(y_test, preds)
roc_auc = metrics.auc(fpr, tpr)

import matplotlib.pyplot as plt
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10249160629086411, 'fraction_numerical': 0.014136773281498498, 'mean_word_length': 4.044117647058823, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '608335', 'license': 'MIT', 'n_tokens_mistral': 3877, 'n_tokens_neox': 3685, 'n_words': 1261, 'path': 'heart_attack_ML.ipynb', 'repo_name': 'knishina/heart_attack', 'size': '11318'}