import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

"""
Explanation: Loan Prediction (AnalyticsVidhya)
Problem Statement
About Company
Dream Housing Finance company deals in all home loans. They have presence across all urban, semi urban and rural areas. Customer first apply for home loan after that company validates the customer eligibility for loan.
Problem
Company wants to automate the loan eligibility process (real time) based on customer detail provided while filling online application form. These details are Gender, Marital Status, Education, Number of Dependents, Income, Loan Amount, Credit History and others. To automate this process, they have given a problem to identify the customers segments, those are eligible for loan amount so that they can specifically target these customers. Here they have provided a partial data set.
Data:
Variable        |   Description
  -------------  | -------------
    Loan_ID      |    Unique Loan ID
    Gender       |     Male/ Female
    Married      |    Applicant married (Y/N)
    Dependents   |    Number of dependents
    Education    |    Applicant Education (Graduate/ Under Graduate)
   Self_Employed |    Self employed (Y/N)
 ApplicantIncome |    Applicant income
CoapplicantIncome |    Coapplicant income
    LoanAmount   |    Loan amount in thousands
Loan_Amount_Term |    Term of loan in months
Credit_History   |    Credit history meets guidelines
Property_Area    |    Urban/ Semi Urban/ Rural
    Loan_Status  |    Loan approved (Y/N) 
Import Libraries
End of explanation
"""


df_train = pd.read_csv("train.csv")
df_test = pd.read_csv("test.csv")

"""
Explanation: Read Data
End of explanation
"""


sns.set_style("darkgrid")

sns.countplot(x='Loan_Status',data=df_train)

temp = df_train.loc[:,['ApplicantIncome', 'CoapplicantIncome', 'LoanAmount', 'Loan_Amount_Term', 'Loan_Status']]

sns.pairplot(temp.dropna(), hue='Loan_Status')

"""
Explanation: Data Exploration
Checking distribution of the target variable
End of explanation
"""


y = df_train["Loan_Status"]

df_train["trainFlag"] = 1
df_test["trainFlag"] = 0
df = pd.concat([df_train.drop('Loan_Status', axis = 1), df_test])

"""
Explanation: Data Cleaning
End of explanation
"""


df.drop('Loan_ID', axis=1, inplace=True)
cat_df = df.select_dtypes(include=['object'])
cat_df.head()

num_df = df.select_dtypes(exclude=['object'])
num_df.head()

"""
Explanation: Seperating categorical and numerical columns for missing data treatment
End of explanation
"""


cat_df = cat_df.apply(lambda x:x.fillna(x.value_counts().index[0]))
cat_df.info()

"""
Explanation: Filling Missing Categorical Column values with the most frequent value
End of explanation
"""


cat_df = pd.get_dummies(cat_df, drop_first=True)
cat_df.head()

"""
Explanation: Converting Categorical Variables to Dummy Variables
End of explanation
"""


from sklearn.preprocessing import Imputer

imp = Imputer(strategy="median")

num_columns = num_df.columns

imp.fit(num_df)

num_df = imp.transform(num_df)

num_df = pd.DataFrame(num_df,columns=num_columns)
num_df.info()

df = pd.concat([cat_df.reset_index(),num_df],axis=1)
df.drop('index',axis=1,inplace=True)
df.head()

"""
Explanation: Imputing Numerical Columns
End of explanation
"""


from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()

le.fit(y)

y = le.transform(y)

"""
Explanation: Encoding target variable to a 0 to (nclasses-1) range
End of explanation
"""


df['TotalIncome'] = df['ApplicantIncome'] + df['CoapplicantIncome']

"""
Explanation: Feature Engineering
Combining Applicant and Coapplicant Income as a single Total Income
End of explanation
"""


df['Amt_pm'] = df.apply(lambda x: (x['LoanAmount']/x['Loan_Amount_Term'])*1000,axis=1)

df.head()

"""
Explanation: Calculating the approximate amount per month the applicant has to pay
End of explanation
"""


df['burden'] = df.apply(lambda x: (x['Amt_pm']/x['TotalIncome'])*100 ,axis=1)

df.head()

df['Appl_perc'] = df.apply(lambda x: (x['ApplicantIncome']/ x['TotalIncome']) *100 , axis=1)

df.drop(['ApplicantIncome','CoapplicantIncome','LoanAmount','Loan_Amount_Term'],axis=1,inplace=True)

"""
Explanation: Calculating the ratio of approx amount per month to be paid and total income of the applicant
End of explanation
"""


train = df.loc[df.trainFlag == 1, df.columns != 'trainFlag']
test = df.loc[df.trainFlag == 0, df.columns != 'trainFlag']

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

train = scaler.fit_transform(train)
test = scaler.fit_transform(test)

"""
Explanation: Scaling the variables so that higher valued variable don't dominate others in ML Algorithms
End of explanation
"""


from sklearn.linear_model import LogisticRegression

lm = LogisticRegression()

from sklearn.preprocessing import LabelEncoder

lm.fit(train,y)

pred = lm.predict(train)

"""
Explanation: Model Training
1. Logistic Regression
End of explanation
"""


from sklearn.metrics import confusion_matrix,classification_report

print(confusion_matrix(y,pred))

print(classification_report(y,pred))

lm.score(train,y)

"""
Explanation: Checking Accuracy on Train Dataset
End of explanation
"""


pred = lm.predict(test)
pred = le.inverse_transform(pred)

final = df_test
final['Loan_Status'] = pred
final = final[["Loan_ID",'Loan_Status']]

final.to_csv("submission.csv")

"""
Explanation: Preparing Submission to solution checker on AnalyticsVidhya
End of explanation
"""


from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV

"""
Explanation: 2. Support Vector Classifier with Gridsearch
End of explanation
"""


params_grid = {'C':[0.1,1,10,100],'gamma':[1,0.1,0.01,0.001]}

grid = GridSearchCV(SVC(),param_grid=params_grid,verbose=3)

grid.fit(train,y)

grid.best_params_

"""
Explanation: Specifying range of values for C and gamma to pick the best value for them
End of explanation
"""


grid.score(train,y)

pred = grid.predict(test)
pred = le.inverse_transform(pred)

final = df_test
final['Loan_Status'] = pred
final = final[["Loan_ID",'Loan_Status']]

final.to_csv("submission.csv")

"""
Explanation: Checking accuracy on train data
End of explanation
"""


from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=10,max_features=0.4,max_depth=5,min_samples_leaf=2)

rf.fit(train,y)

"""
Explanation: 3. RandomForest Classifier
End of explanation
"""


rf.score(train,y)

pred = rf.predict(test)
pred = le.inverse_transform(pred)

final = df_test
final['Loan_Status'] = pred
final = final[["Loan_ID",'Loan_Status']]

final.to_csv("submission.csv")

"""
Explanation: Checking accuracy on train data
End of explanation
"""


