"""
# **Heart Disease (EDA & ML)**
"""
"""
## **Exploratory Data Analysis (EDA)**
"""
"""
#### **Step 1: Loading and Displaying tabular data**
"""
import pandas as pd

# Not limiting the column number when displaying dataframe
pd.set_option("display.max_columns", None)
df = pd.read_csv("../input/heart-failure-prediction/heart.csv", sep = r',', skipinitialspace = True)
df.head()
df.tail()
df.shape
"""
#### **Step 2: Basic statistics about the dataframe and specific columns**
"""
print(df.columns)
rows = df.shape[0]
cols = df.shape[1]

print("Before cleaning, there are " + str(rows) + " rows and " + str(cols) + " columns in this dataframe.")
dupRows = df.duplicated().sum()
print("There are " + str(dupRows) + " duplicated rows in the dataframe.")
df.isnull().sum()
df.nunique()
df.info()
df.dtypes.value_counts()
df.describe()
df.memory_usage()
import seaborn as sns
import matplotlib.pyplot as plt

plt.figure(figsize = (16, 16))
plt.title("Age Distribution", fontsize = 20)
plt.xlabel("Age", fontsize = 16)
plt.ylabel("Number of occurences", fontsize = 16)
sns.histplot(df["Age"], color = "gold")
plt.show()
"""
#### **Step 3: Correlation, Interdependencies, Relations & more**
"""
df.corr()
import seaborn as sns
import matplotlib.pyplot as plt

correlations = df.corr()

plt.figure(figsize = (16, 16))
plt.title("Heatmap displaying the correlations between all columns", fontsize = 20)
sns.heatmap(correlations, annot = True, cmap = "YlOrBr", cbar_kws={'label': 'Correlation Value', 'orientation': 'horizontal'})
"""
How do the columns correlate with our target column "HeartDisease"?
"""
hd = df.corr()["HeartDisease"]
hd = pd.DataFrame(hd)
hd
%matplotlib inline

plt.figure(figsize = (16, 12))
plt.title("Correlations between input columns and target column 'HeartDisease'", fontsize = 20)
plt.xlabel("Columns", fontsize = 16)
plt.ylabel("Correlation factor", fontsize = 16)
plt.plot(hd, color = "orange", linestyle = "", marker = "X")
plt.show()
sns.pairplot(df)
"""
How many people have heart disease and how many don't?
"""
no = df.value_counts(["HeartDisease"])[0]
yes = df.value_counts(["HeartDisease"])[1]

print(str(no) + " patients do not have heart disease, while " + str(yes) + " do.")
"""
Are there more men or more women with heart disease and what is their percentage?
"""
pd.crosstab(df["Sex"], df["HeartDisease"])
"""
There are way more men with heart disease than women, both in % and in absolute numbers.
"""
ct = pd.crosstab(df["Sex"], df["HeartDisease"]) 

plt.figure(figsize = (16, 12))
plt.title("Crosstab showing how many patients of which sex were diagnosed with heart disease", fontsize = 20)
sns.heatmap(ct, cmap = "PiYG", annot = True, cbar = True, fmt = "g", cbar_kws={'label': 'Absolute number of occurences', 'orientation': 'horizontal'})
"""
How many people of what age had to die?
"""
pd.crosstab(df["Age"], df["HeartDisease"])
ct = pd.crosstab(df["Age"], df["HeartDisease"]) 

plt.figure(figsize = (16, 16))
plt.title("Crosstab showing how many patients of what age were diagnosed with heart disease", fontsize = 20)
sns.heatmap(ct, cmap = "BuPu", annot = True, cbar = True, fmt = "g", cbar_kws={'label': 'Absolute number of occurences', 'orientation': 'horizontal'})
"""
#### **Step 4: Interactive Profiling**
"""
pip install pandas-profiling[notebook]
import pandas_profiling
from pandas_profiling import ProfileReport

profile = ProfileReport(df, title = "Pandas Profiling Report", explorative = True)

profile.to_widgets()
"""
#### ================================================================================================================
"""
"""
## **Machine Learning (ML)**
"""
"""
#### **Step 1: Pre-Cleaning & Pre-Processing data**
"""
df.head()
df = df.dropna()
df = df.replace("M", 1)
df = df.replace("F", 2)
df["ChestPainType"] = df["ChestPainType"].astype(str)
df["RestingECG"] = df["RestingECG"].astype(str)
df["ExerciseAngina"] = df["ExerciseAngina"].astype(str)
df["ST_Slope"] = df["ST_Slope"].astype(str)

from sklearn import preprocessing

number = preprocessing.LabelEncoder()

df["ChestPainType"] = number.fit_transform(df["ChestPainType"])
df["RestingECG"] = number.fit_transform(df["RestingECG"])
df["ExerciseAngina"] = number.fit_transform(df["ExerciseAngina"])
df["ST_Slope"] = number.fit_transform(df["ST_Slope"])

df.head()
"""
#### **Step 2: Defining input/output and Splitting dataframe**
"""
from sklearn.model_selection import train_test_split

X = df.drop(["HeartDisease"], axis = 1)
y = df["HeartDisease"]

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 0, test_size = 0.1)
"""
#### **Step 3: Models**
"""
"""
#### Logistic Regression
"""
from sklearn.linear_model import LogisticRegression

model = LogisticRegression(solver = "saga", max_iter = 10000)
model.fit(X_train, y_train)
model.score(X_test, y_test)
"""
#### Random Forest
"""
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(criterion = "entropy")
model.fit(X_train, y_train)
model.score(X_test, y_test)
"""
#### Decision Tree
"""
from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier(criterion = "entropy")
model.fit(X_train, y_train)
print(model.score(X_test, y_test))
from sklearn.model_selection import validation_curve
from sklearn.tree import DecisionTreeClassifier
import numpy as np

param_range = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])

train_scores, test_scores = validation_curve(DecisionTreeClassifier(), X_train, y_train, param_name = "max_depth", param_range = param_range)

%matplotlib inline
import matplotlib.pyplot as plt

plt.figure(figsize = (16, 12))

plt.plot(param_range, np.mean(train_scores, axis = 1))
plt.plot(param_range, np.mean(test_scores, axis = 1))

plt.title("How does the tree depth influence the accuracy?", fontsize = 20)
plt.xlabel("depth levels of model", fontsize = 15)
plt.ylabel("model accuracy", fontsize = 15)

# Adding a legend
plt.legend(["train", "test"], loc = "upper left", fontsize = 12)

plt.show()
"""
#### SVM with RBF-Kernel
"""
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
from sklearn.svm import SVC

model = SVC(kernel = "rbf", gamma = 0.01, C = 5)
model.fit(X_train, y_train)
model.score(X_test, y_test)
"""
#### Gaussian NB
"""
from sklearn.naive_bayes import GaussianNB

model = GaussianNB()
model.fit(X_train, y_train)
model.score(X_test, y_test)
"""
#### KNN
"""
from sklearn.neighbors import KNeighborsClassifier

model = KNeighborsClassifier(n_neighbors = 18)
model.fit(X_train, y_train)
model.score(X_test, y_test)
from sklearn.model_selection import learning_curve
from sklearn.neighbors import KNeighborsClassifier
from sklearn.utils import shuffle

X_train, y_train = shuffle(X_train, y_train)

import numpy as np

train_sizes_abs, train_scores, test_scores = learning_curve(KNeighborsClassifier(), X_train, y_train)

%matplotlib inline
import matplotlib.pyplot as plt

plt.figure(figsize = (16, 12))

plt.plot(train_sizes_abs, np.mean(train_scores, axis = 1))
plt.plot(train_sizes_abs, np.mean(test_scores, axis = 1))

plt.title("Learning Curve KNN", fontsize = 20)
plt.xlabel("Number of neighbors", fontsize = 15)
plt.ylabel("Model Accuracy", fontsize = 15)

# Adding a legend
plt.legend(["train", "test"], loc = "upper right", fontsize = 12)

plt.show()
"""
#### Logistic Regression with pre-scaled data
"""
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)


from sklearn.linear_model import LogisticRegression

model = LogisticRegression(solver = "saga", max_iter = 10000)
model.fit(X_train, y_train)
model.score(X_test, y_test)