import os
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import scikitplot as skplt
import matplotlib.gridspec as gridspec
%matplotlib inline
from IPython.display import display_html
import statsmodels.formula.api as smf
import statsmodels.api as sm

from sklearn import model_selection
from sklearn import metrics

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC 
from sklearn.linear_model import LogisticRegression

from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, accuracy_score
import tensorflow as tf
import matplotlib.gridspec as gridspec
from sklearn.metrics import roc_curve, auc

blue_red = ['#74a09e','#86c1b2','#98e2c6','#f3c969','#f2a553', '#d96548', '#c14953']
sns.palplot(sns.color_palette(blue_red))

# Set Style
sns.set_style("whitegrid")
sns.despine(left=True, bottom=True)
seed = 42
tf.random.set_seed(
    seed
)

df = pd.read_csv('../input/coronary-artery-disease/Coronary_artery.csv')
print(print('Features:{}'.format(df.columns.tolist())))
df['class'].replace({4: 3}, inplace = True)
df.head(5)
df.info()
df.describe()
print(df.shape)
print(df.isnull().values.any())
df2 = pd.read_csv('../input/coronary-artery-disease/data.csv')
df2.info()
df2 = df2[~df2.isin(['?'])]
df2 = df2.dropna(axis=0)
df2['class'].replace({4: 3}, inplace = True)
df2.info()
df2.head()
correlation_mat = df2.corr()
plt.figure(figsize=(20,20))
ax=sns.heatmap(correlation_mat, annot = True)
plt.show(ax)
#sns.pairplot(df2, height = 1.5, palette = 'rocket')
black_red = [
    '#1A1A1D', '#4E4E50', '#C5C6C7', '#6F2232', '#950740', '#C3073F'
]
fig = plt.figure(constrained_layout = True, figsize = (25,12))

#create grid

grid = gridspec.GridSpec(ncols = 4, nrows = 2, figure = fig)

ax1 = fig.add_subplot(grid[0, :2])
ax1.set_title('Gender Distribution')


sns.countplot(df['sex'],
             alpha = 0.9,
             hue = df['class'],
             ax = ax1,
             palette = 'rocket',
             order=df['sex'].value_counts().index)

ax1.legend()
plt.xticks(fontsize = 14)

ax2 = fig.add_subplot(grid[0, 2:])
ax2.set_title('Chest Pain Distribution')
sns.countplot(df['cp'],
             alpha = 0.9,
             hue = df['class'],
             ax = ax2, 
             palette = 'rocket',
             order=df['cp'].value_counts().index)
ax2.legend()
plt.xticks( fontsize = 14)

ax3 = fig.add_subplot(grid[1, :2])
ax3.set_title('Resting Electrographic Results Distribution')
sns.countplot(df['restecg'],
             alpha = 0.9,
             hue = df['class'],
             ax = ax3, 
             palette = 'rocket',
             order=df['restecg'].value_counts().index)
ax3.legend()
plt.xticks(fontsize = 14)

ax4 = fig.add_subplot(grid[1, 2:])
ax4.set_title('Defect Type Distribution')
sns.countplot(df['thal'],
             alpha = 0.9,
             hue = df['class'],
             ax = ax4, 
             palette = 'rocket',
             order=df['thal'].value_counts().index)
ax4.legend()
plt.xticks(fontsize = 14)
plt.show()
fig = plt.figure(constrained_layout = True, figsize = (15,9))

#create grid

grid = gridspec.GridSpec(ncols = 1, nrows = 4, figure = fig)
ax1 = fig.add_subplot(grid[0, :])

sns.distplot(df.age, ax = ax1, color = blue_red[1])
ax1.set_title('Age Distribution')

ax2 = fig.add_subplot(grid[1, :])
sns.distplot(df.chol, ax = ax2, color = blue_red[2])
ax2.set_title('Cholestrol Distribution')


ax3 = fig.add_subplot(grid[2, :])
sns.distplot(df.trestbps, ax = ax3, color = blue_red[3])
ax3.set_title('Resting Blood Sugar Distribution')

ax4 = fig.add_subplot(grid[3, :])
sns.distplot(df.thalach, ax = ax4, color = blue_red[4])
ax4.set_title('Maximum Heart Rate Distribution')
import plotly.express as px
fig = px.sunburst(data_frame = df,
                 path = [ 'sex','class','cp'],
                 color = 'class',
                 maxdepth = -1,
                 title = 'Sunburst Chart gender > class > chestpain')
fig.update_traces(textinfo = 'label+percent parent')
fig.update_layout(margin=dict(t=0, l=0, r=0, b=0))
fig.show()
print(df2.sex.unique())
print(df2.cp.unique())
print(df2.fbs.unique())
print(df2.restecg.unique())
print(df2.exang.unique())
print(df2.slope.unique())
print(df2.ca.unique())
print(df2.thal.unique())
df_new = df2.rename(columns={'class': 'label'})
formula = 'label ~ age+sex+cp+trestbps+chol+fbs+restecg+thalach+exang+oldpeak+slope+ca+thal'
result = smf.glm(formula = formula, data=df_new).fit()
print(result.summary())
#df_new['label'].replace({4: 3}, inplace = True)
X = df_new[['cp', 'restecg', 'thalach', 'oldpeak', 'slope', 'ca', 'thal']]
Y = df_new['label']
X = pd.get_dummies(X, columns=['cp', 'restecg', 'slope', 'ca', 'thal'])
X.head()
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, Y, test_size=0.20, random_state=42)
"""
# Decision Tree
"""
tree_model = DecisionTreeClassifier(max_depth = 25)
tree_model.fit(X_train, y_train)
y_pred_tree = tree_model.predict(X_test)

y_pred_train_tree = tree_model.predict(X_train)
tree_confusion = metrics.confusion_matrix(y_train, y_pred_train_tree)
print('Confusion Matrix for Train:\n{}'.format(tree_confusion))
acc=accuracy_score(y_train, y_pred_train_tree) 
print('Train case accuracy is :'+ format(acc))
print('\n')

y_pred_test_tree = tree_model.predict(X_test)
tree_confusion = metrics.confusion_matrix(y_test, y_pred_test_tree)
print('Confusion Matrix for Test:\n{}'.format(tree_confusion))
acc= accuracy_score(y_test, y_pred_test_tree)
print('Test case accuracy is :'+ format(acc))
print('\n')

print(classification_report(y_test, y_pred_test_tree))
y_pred_prob_tree = tree_model.predict_proba(X_test)

skplt.metrics.plot_roc(y_test, y_pred_prob_tree, figsize = (10, 10))
plt.show()
"""
# Random Forest
"""
# Feature Scaling
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)


# Fitting Random Forest Classification to the Training set
classifier = RandomForestClassifier(n_estimators = 15, criterion = 'entropy', random_state = 42)
classifier.fit(X_train, y_train)

y_pred_train = classifier.predict(X_train)

# Making the Confusion Matrix
random_confusion = metrics.confusion_matrix(y_train, y_pred_train)
print('Confusion Matrix for train:\n{}'.format(random_confusion))
acc=accuracy_score(y_train, y_pred_train)
print('Train case accuracy is :'+ format(acc))
print('\n')
y_pred = classifier.predict(X_test)

# Making the Confusion Matrix
random_confusion = metrics.confusion_matrix(y_test, y_pred)
print('Confusion Matrix for test:\n{}'.format(random_confusion))
acc=accuracy_score(y_test, y_pred)
print('Test case accuracy is :'+ format(acc))
print('\n')
print(classification_report(y_test, y_pred))
y_pred_prob_rf = classifier.predict_proba(X_test)
skplt.metrics.plot_roc(y_test, y_pred_prob_rf, figsize = (10, 10))
plt.show()
"""
# SVM
"""
svm_model_linear = SVC(decision_function_shape='ovo',kernel = 'poly', C = 1, probability = True).fit(X_train, y_train) 
#kernel='poly' gives best result

svm_predictions_train = svm_model_linear.predict(X_train) 
cm1 = metrics.confusion_matrix(y_train, svm_predictions_train) 
acc1=accuracy_score(y_train, svm_predictions_train)
print('Confusion Matrix for train:\n{}'.format(cm1))
print('Train case accuracy is :'+ format(acc1))
print('\n')
svm_predictions = svm_model_linear.predict(X_test) 
# creating a confusion matrix  and finding accuracy
cm = metrics.confusion_matrix(y_test, svm_predictions) 
acc=accuracy_score(y_test, svm_predictions)
print('Confusion Matrix for test:\n{}'.format(cm))
print('Test case accuracy is :'+ format(acc))
print('\n')
print(classification_report(y_test, svm_predictions))
y_pred_prob_svm = svm_model_linear.predict_proba(X_test)
skplt.metrics.plot_roc(y_test, y_pred_prob_svm, figsize = (10, 10))
plt.show()
"""
# KNN
"""
# training a KNN classifier 

knn = KNeighborsClassifier(n_neighbors = 7).fit(X_train, y_train) 
knn_predictions_train = knn.predict(X_train) 
cm1 = metrics.confusion_matrix(y_train, knn_predictions_train) 
acc1=accuracy_score(y_train, knn_predictions_train)
print('Confusion Matrix for train:\n{}'.format(cm1))
print('Train case accuracy is :'+ format(acc1))
print('\n')
knn_predictions = knn.predict(X_test) 
# creating a confusion matrix  and finding accuracy
cm = metrics.confusion_matrix(y_test, knn_predictions) 
acc=accuracy_score(y_test, knn_predictions)
print('Confusion Matrix for test:\n{}'.format(cm))
print('Test case accuracy is :'+ format(acc))
print('\n')
print(classification_report(y_test, knn_predictions))
y_pred_prob_knn = knn.predict_proba(X_test)
skplt.metrics.plot_roc(y_test, y_pred_prob_knn, figsize = (10, 10))
plt.show()
"""
# Logistic Regression

"""

# instantiate model
logreg = LogisticRegression()

# fit model
logreg.fit(X_train, y_train)
y_pred_train = logreg.predict(X_train)
y_pred_class = logreg.predict(X_test)
confusion1 = metrics.confusion_matrix(y_train, y_pred_train)
acc=accuracy_score(y_train, y_pred_train)
confusion = metrics.confusion_matrix(y_test, y_pred_class)
acc1=accuracy_score(y_test, y_pred_class)
print(confusion1)
print('Train case accuracy is :'+ format(acc))
print('\n')
print(confusion)
print('Test case accuracy is :'+ format(acc1))
print('\n')
print(classification_report(y_test, y_pred_class))
y_pred_prob_log = logreg.predict_proba(X_test)
#plt.figure(figsize = (10, 10))
skplt.metrics.plot_roc(y_test, y_pred_prob_log, figsize = (10, 10))
plt.show()
"""
# Neural Net
"""
X= df2[['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg', 'thalach','exang', 'oldpeak', 'slope', 'ca', 'thal']]

y= df2['class']
X = np.asarray(X).astype('float32')
y = np.asarray(y).astype('float32')
# Split the dataset using a 70:30 split
X_train1, X_test1, y_train1, y_test1 = model_selection.train_test_split(X, y, test_size=0.20, random_state=0)

#Check the shape of each variable, remember the X variable must be in matrix form and the y varibale a vector
X_train1.shape, y_train1.shape, X_test1.shape, y_test1.shape
from keras.utils.np_utils import to_categorical

Y_train1 = to_categorical(y_train1, num_classes=None)
Y_test1 = to_categorical(y_test1, num_classes=None)
print(Y_train1.shape)
print(Y_train1[:10])
import tensorflow as tf
from keras.models import Sequential
from keras.layers.core import Flatten, Dense, Dropout
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
model = Sequential()
model.add(Dense(16, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(10, kernel_initializer='normal', activation='relu'))
model.add(Dense(8, kernel_initializer='normal', activation='relu'))
model.add(Dense(4, activation='softmax'))
#compiling model
adam = Adam(lr = 0.001)
model.compile(loss="categorical_crossentropy", optimizer=adam, metrics=["accuracy"])
estop = EarlyStopping(patience=10, mode='min', min_delta=0.001, monitor='val_loss')

history = model.fit(X_train1, Y_train1, validation_data=(X_test1, Y_test1), epochs=100, batch_size=10, verbose = 1, callbacks = [estop])
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('MODEL ACCURACY')
plt.ylabel('Accuracy')
plt.xlabel('No. of epochs')
plt.legend(['train', 'val'], loc='upper left')
plt.show()
categorical_pred = np.argmax(model.predict(X_train1), axis=1)

print('Results for Categorical Model')
print(accuracy_score(y_train1, categorical_pred))
print(classification_report(y_train1, categorical_pred))
probas = model.predict_proba(X_test1, batch_size=10)
skplt.metrics.plot_roc(y_test1, probas, figsize = (10, 10))
"""
# Binary NN
"""
Y_train_binary = y_train1.copy()
Y_test_binary = y_test1.copy()

Y_train_binary[Y_train_binary > 0] = 1
Y_test_binary[Y_test_binary > 0] = 1

print(Y_train_binary[:20])
model2 = Sequential()
model2.add(Dense(8, input_dim=13, kernel_initializer='normal', activation='relu'))
model2.add(Dense(4, kernel_initializer='normal', activation='relu'))
model2.add(Dense(1, activation='sigmoid'))
#compiling model
adam = Adam(lr = 0.001)
model2.compile(loss="binary_crossentropy", optimizer=adam, metrics=["accuracy"])
history2 = model2.fit(X_train1, Y_train_binary, validation_data=(X_test1, Y_test_binary), epochs=100, batch_size=10, verbose = 1, callbacks = [estop])
plt.plot(history2.history['accuracy'])
plt.plot(history2.history['val_accuracy'])
plt.title('MODEL ACCURACY')
plt.ylabel('Accuracy')
plt.xlabel('No. of epochs')
plt.legend(['train', 'val'], loc='upper left')
plt.show()
y_pred_prob = model2.predict_proba(X_test1)
fpr1, tpr1, thresholds1 = metrics.roc_curve(Y_test_binary, y_pred_prob)

random_probs = [0 for i in range(len(y_test))]
p_fpr, p_tpr, _ = metrics.roc_curve(y_test, random_probs, pos_label=1)
plt.style.use('seaborn')

# plot roc curves
plt.plot(fpr1, tpr1, linestyle='--',color='orange', label='Test Data')
plt.plot(p_fpr, p_tpr, linestyle='--', color='blue', label = 'Threshold')
# title
plt.title('ROC curve for Logistic Regression')
# x label
plt.xlabel('False Positive Rate')
# y label
plt.ylabel('True Positive rate')

plt.legend(loc='best')
plt.savefig('ROC',dpi=300)
plt.show();
print('AUC socre for Test data: {}'.format(metrics.roc_auc_score(Y_test_binary, y_pred_prob)))
binary_pred = np.round(model2.predict(X_test1)).astype(int)

print('Results for Binary Model')
print(accuracy_score(Y_test_binary, binary_pred))
print(classification_report(Y_test_binary, binary_pred))