# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python [conda env:nlp]
#     language: python
#     name: conda-env-nlp-py
# ---

# # Desafio Data Science

# Serão feitos analises e exploração de dados para responder questões do teste.

# +
# import packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.ensemble import ExtraTreesClassifier
from sklearn.metrics import confusion_matrix as cm
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.linear_model import LogisticRegression

# %matplotlib inline
# -

# read data
df = pd.read_csv('../data/bank-full.csv', sep= ";")
df.head()

# describe data
des = df.describe()
des.head()

# check if any column has null values
cols = df.columns
for col in cols:
    print(col + ' ' + 'has values: ', df[cols].isnull().any())

# ## 1. Qual profissão tem mais tendência a fazer um empréstimo? De qual tipo?

# +
# Qual % de clientes possui apenas um tipo de emprestimo e qual % de ambos e qual nao tem emprestimo nenhum
both = 0
housing = 0
loan = 0
noloan = 0

for i in range(0, len(df)):
    if (df.iloc[i].housing == 'yes'):
        if (df.iloc[i].loan == 'yes'):
            both = both + 1
        else:
            housing = housing + 1
    elif (df.iloc[i].loan == 'no'):
        noloan = noloan + 1
    else:
        loan = loan + 1

bothp = round(both / len(df) * 100, 1)
housingp = round(housing / len(df) * 100, 1)
loanp = round(loan / len(df) * 100, 1)
noloanp = round(noloan / len(df) * 100, 1)

print('both: ' + str(bothp) + '%')
print('housing: ' + str(housingp) + '%')
print('loan: ' + str(loanp) + '%')
print('noloan: ' + str(noloanp) + '%')

# +
# Add uma coluna adicional com o tipo de empréstimo de cada cliente
df1 = []

for i in range(0, len(df)):
    if (df.iloc[i].housing == 'yes'):
        if (df.iloc[i].loan == 'yes'):
            df1.append(3)
        else:
            df1.append(1)
    elif (df.iloc[i].loan == 'no'):
        df1.append(0)
    else:
        df1.append(2)


df1 = pd.DataFrame(df1)
df = pd.concat([df, df1], axis = 1)
df.head()
# -

# Histrograma de profissoes por tipo de emprestimo
prof = df[0].groupby([df['job'], df[0]]).count()
df_jl = pd.DataFrame(prof.unstack())
df_jl.columns = ['noloan', 'housing', 'loan', 'both']
df_jl.plot(kind='bar', title ="Histograma de emprestimos por job", figsize=(18, 6), legend=True, fontsize=12)
plt.show()

# ### Resposta Questao 1:
#
# Confirendo no histograma, podemos notar que tem mais tendência a fazer um empréstimo é a **blue-collar** e o tipo de empréstimo é o **housing**

# ## 2. Fazendo uma relação entre número de contatos e sucesso da campanha quais são os pontos relevantes a serem observados?

# +
# Dataset e os gráficos de barra para encontrar as relações.
df_camp = []
df_cont = []

for i in range(0, len(df)):
    if (df.iloc[i].y == 'yes'):
        df_camp.append(df.iloc[i].campaign)
        df_cont.append(df.iloc[i].contact)
    
df_camp = pd.DataFrame(df_camp)
df_cont = pd.DataFrame(df_cont)
df_camp = pd.concat([df_camp, df_cont], axis=1)

df_camp.columns=['nrcontacts', 'typecontacts']
cont = df_camp['nrcontacts'].groupby([df_camp['nrcontacts']]).count()


min(df_camp['nrcontacts'])
max(df_camp['nrcontacts'])

cont = pd.DataFrame(cont)

# Plot bar
sns.set(rc={'figure.figsize':(18,6)})
sns.barplot(x=cont.index, y=cont.nrcontacts)

for i in range(0, len(cont)):
    nrcont = i + 1
    perc = cont.iloc[i]/len(df_camp) * 100
    perc = int(perc)
    print('Nr. de contatos: ' + str(nrcont) + ' Porcentagem: ' + str(perc) + ' %')
    perc = 0
# -

# ### Resposta Questão 2:
# Observando o gráfico de barras, podemos notar que o maior sucesso da campanha está
# **no primeiro e no segundo contato**. O terceiro contato ainda tem relevância com 11% aproximadamente, mas
# a partir do quarto contato, o percentual de sucessos por número de contatos passa a não ter relevância. Ou seja, um grande numero de contatos nao aumenta a chance de sucesso.

# ## 3. Baseando-se nos resultados de adesão desta campanha qual o número médio e o máximo de ligações que você indica para otimizar a adesão?
# Para fazer uma análise das ligações, vamos verificar os modos de contato com o cliente que foram utilizados.
# Vamos reduzir o dataset e utilizar os dados de um número máximo de seis contatos pois atingem no total,
# 93% do total de sucessos na campanha.

# +
df_camp_sub = []
for j in range(0, len(df_camp)):
    if (df_camp.iloc[j].nrcontacts <= 6):
        df_camp_sub.append(df_camp.iloc[j])

df_camp_sub = pd.DataFrame(df_camp_sub)
camp_sub = df_camp_sub['typecontacts'].groupby([df_camp_sub['nrcontacts'], df_camp_sub['typecontacts']]).count()

camp_sub = pd.DataFrame(camp_sub)
camp_sub.columns = ['nrtypecontacts']
camp_sub.reset_index(inplace=True)

sns.set(rc={'figure.figsize':(18,6)})
ax = sns.barplot(x = 'nrcontacts', y = 'nrtypecontacts', hue = 'typecontacts', data=camp_sub)
# -

# ### Resposta Questão 3:
# Verificamos que o principal modo é através de ligações telefônicas,
# sejam através de celular ou linha fixa. Com isto, eu posso indicar que o número médio de
# **3 ligações pois atingiríamos 85% de sucesso e o número máximo de 6 ligações onde atingiríamos 93% de sucesso.**

# ## 4. O resultado da campanha anterior tem relevância na campanha atual?
#

# Bar plot about outcome
sns.set(rc={'figure.figsize':(18,6)})
sns.countplot(x=df['poutcome'], data=df)

# Vamos definir duas hipotesis:
#     
# - Hipótese 0 : A diferença entre as taxas é zero
# - Hipótese 1 : A diferença entre as taxas NÃO é zero
#
# Como se trata de uma distribuição bimodal será utilizado o t_test

grouped4 = df.pivot_table(values='age', index='poutcome', columns='y', aggfunc='count')
grouped4.head()

# +
data = df.copy()
filtering = (data['poutcome']=='failure') | (data['poutcome']=='success')

# Pega amostras com 'poutcome' válidos
ex2 = data[['poutcome','y']][filtering]

# Transforma 'y' e 'poutcome' em valores numéricos (label encoding) 
bool_y, label_y = pd.factorize(ex2['y'])        
bool_p, label_p = pd.factorize(ex2['poutcome']) 

# Plot confusion matrix
df_cm = pd.DataFrame(cm(bool_p, bool_y), index=label_p, columns=label_p)
plt.figure(figsize = (18,6))
plot = sns.heatmap(df_cm, annot=True, annot_kws={"size": 18}, fmt="d")
plot.yaxis.set_ticklabels(plot.yaxis.get_ticklabels(), rotation=0, ha='right', fontsize=14)
plot.set_ylim([0,2])
plot.xaxis.set_ticklabels(plot.xaxis.get_ticklabels(), rotation=45, ha='right', fontsize=14)
sns.set(font_scale=1)
plt.ylabel('Previous Campaign')
plt.xlabel('Current Campaign')
plt.title("Confusion Matrix (Previous vs Current Result)\n", size=20)
plt.show()
# -

# ### Resposta Questao 4:
# Observando a matriz de confusão, podemos notar que há uma grande tendência de que indivíduos que recusaram a campanha anterior também recusarão a atual. Nota-se, também, que boa parcela dos sucessos na campanha anterior se mantém na campanha atual.
#
# A partir da análise, podemos assumir que o resultado da campanha anterior é relevante para atual.

# ## 5. Qual o fator determinante para que o banco exija um seguro de crédito?
#

# +
# Features importantes
df5 = pd.DataFrame(data.iloc[:,:8])

# Separamos features e target variable
X = df5.drop('default', axis=1)
Y = df5[['default']]

# Trasformamos texto para dado numérico (label encoding)
for col in list(set(X.columns)-set(['age', 'balance'])):
    X[col] = pd.factorize(X[col])[0]

# Instanciamos e treinamos o classificador
model = ExtraTreesClassifier()
model.fit(X, Y.values.ravel())

main_features = pd.Series(model.feature_importances_, index=X.columns)
plt.figure(figsize=(18, 6))
main_features.nlargest(5).plot(kind='barh')
plt.xlabel("Importance")
plt.ylabel("Features")
plt.title("Classifying Relevant Features", size=16)
plt.show()
# -

# Baseados na classificacao, e possivel inferir que as features **balance e age** sao as mais relevantes para a analise. Portanto, iremos agrupar os valores delas respeito a variavel **default**.

# +
df = pd.DataFrame(data[['age','balance','default']])

# Plotando grupo 'YES'
plt.figure(figsize=(18, 6))
fig1, ax1 = plt.subplots(1, 2, sharex="col", figsize=(10,5))
fig1.suptitle("Yes Group", size=22)
ax1[0].title.set_text("Balance")
ax1[1].title.set_text("Age")
ax1[0].set_ylabel("Amount of Clients")
ax1[0].set_xlabel("Balance Bins")
ax1[1].set_xlabel("Age Bins")

df[df['default']=='yes']['balance'].hist(ax=ax1[0],bins=50)
df[df['default']=='yes']['age'].hist(ax=ax1[1], bins=50)

# Plotando grupo 'NO'
plt.figure(figsize=(18, 6))
fig2, ax2 = plt.subplots(1, 2, sharex="col", figsize=(10,5))
fig2.suptitle("No Group", size=22)
ax2[0].title.set_text("Balance")
ax2[1].title.set_text("Age")
ax2[0].set_ylabel("Amount of Clients")
ax2[0].set_xlabel("Balance Bins")
ax2[1].set_xlabel("Age Bins")

df[df['default']=='no']['balance'].hist(ax=ax2[0],bins=50)
df[df['default']=='no']['age'].hist(ax=ax2[1], bins=50)

plt.show()


# -

# ### Resposta Questao 5:
# O fator determinante e a idade do cliente, o banco oferece credito default para individuos que estejam na idade economica ativa **21<x<60**.

# ## 6. Quais são as características mais proeminentes de um cliente que possua empréstimo imobiliário?
#
# Nesta secao, usaremos: Weight of Evidence e Information Value.

def iv(df, col, targ):
    event_total = len(df[df[targ]=='yes'])
    nonevent_total = len(df[df[targ]=='no'])

    elements = list(df[col].unique())
    woe_vals = []
    iv_vals = []
  
    # Dividimos os dados em dois grupos: evento e não-evento
    event = df[df[targ]=='yes']   
    nonevent = df[df[targ]=='no']
  
    # Calculamos WoE e IV para cada uma das variaveis de uma coluna
    for e in elements:
        event_percent = len(event[event[col]==e])/event_total           
        nonevent_percent = len(nonevent[nonevent[col]==e])/event_total
        woe_vals.append(np.log(event_percent/nonevent_percent))
        iv_vals.append((event_percent-nonevent_percent)*woe_vals[-1])

    return pd.DataFrame(zip(woe_vals, iv_vals), index=elements, columns=['woe','iv'])


# +
# Pegamos apenas atributos úteis
df = pd.DataFrame(data.iloc[:,:8])

# Discretizamos 'balance' e 'age' (binning)
df['age_bin'] = pd.qcut(df['age'], 7) 
df['balance_bin'] = pd.qcut(df['balance'], 10)
df = df.drop(labels=['balance','age'], axis=1)
df.head()

# +
# Aplicando a funcao iv
iv_totals = []
index = list(df.drop('housing', axis=1).keys())
for att in index:
    iv_totals.append(iv(df, att, 'housing')['iv'].sum())

df_iv = pd.DataFrame(iv_totals, index=index, columns=['IV'])
df_iv.sort_values(by='IV', ascending=False)
# -

# ### Resposta Questao 6:
# Basedos nos resultados apos aplicar o Weight of Evidence e Information Value, a **idade e o emprego** da pessoa resultam ser mais relevantes para avaliar se apresenta ou nao emprestimo imobiliario.



StarcoderdataJupyterScriptsDedupFiltered