<jupyter_start><jupyter_text><jupyter_code>import pandas as pd<jupyter_output><empty_output><jupyter_text>Aula 1<jupyter_code>df_clientes_cadastrados = pd.read_csv('https://raw.githubusercontent.com/HenriqueCCdA/bootCampAluraDataScience/master/modulo6/Dados/clientes_cadastrados.csv')
df_clientes_cadastrados.head()
df_clientes_cadastrados.shape
df_clientes_cadastrados['ID_Cliente'].value_counts()
df_clientes_cadastrados.duplicated().sum()
df_clientes_cadastrados[df_clientes_cadastrados['ID_Cliente'].duplicated(keep=False)].shape
id_repetidos = df_clientes_cadastrados[df_clientes_cadastrados['ID_Cliente'].duplicated(keep=False)]['ID_Cliente']
id_repetidos
df_clientes_cadastrados_ID_unicos = df_clientes_cadastrados.drop(id_repetidos.index)
df_clientes_cadastrados_ID_unicos.head(n=20)
df_clientes_cadastrados_ID_unicos.isnull().sum()
df_clientes_cadastrados_ID_unicos.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
Int64Index: 438463 entries, 0 to 438556
Data columns (total 18 columns):
 #   Column                 Non-Null Count   Dtype  
---  ------                 --------------   -----  
 0   ID_Cliente             438463 non-null  int64  
 1   Genero                 438463 non-null  object 
 2   Tem_Carro              438463 non-null  int64  
 3   Tem_Casa_Propria       438463 non-null  int64  
 4   Qtd_Filhos             438463 non-null  int64  
 5   Rendimento_Anual       438463 non-null  float64
 6   Categoria_de_renda     438463 non-null  object 
 7   Grau_Escolaridade      438463 non-null  object 
 8   Estado_Civil           438463 non-null  object 
 9   Moradia                438463 non-null  object 
 10  Idade                  438463 non-null  float64
 11  Tem_Celular            438463 non-null  int64  
 12  Tem_telefone_trabalho  438463 non-null  int64  
 13  Tem_telefone_fixo      438463 non-null  int64  
 14  Tem_email              438463 non-nu[...]<jupyter_text>Aula 2  Aula 2.1<jupyter_code>colunas_quantitativas = ['Idade', 'Qtd_Filhos', 'Rendimento_Anual', 'Anos_empregado', 'Tamanho_Familia']
df_clientes_cadastrados_ID_unicos[colunas_quantitativas].describe()
df_clientes_cadastrados_ID_unicos.query("Anos_empregado <= 0")[['Anos_empregado','Categoria_de_renda']].value_counts()
df_clientes_cadastrados_ID_unicos['Anos_empregado'] = df_clientes_cadastrados_ID_unicos['Anos_empregado'].replace(-1000.7, -1)
df_clientes_cadastrados_ID_unicos.query("Anos_empregado <= 0")[['Anos_empregado','Categoria_de_renda']].value_counts()
df_clientes_cadastrados_ID_unicos[colunas_quantitativas].describe()<jupyter_output><empty_output><jupyter_text>Aula 2.2<jupyter_code>import seaborn as sns
import matplotlib.pyplot as plt
sns.set()
sns.histplot(data=df_clientes_cadastrados_ID_unicos, x='Rendimento_Anual', bins=10)
plt.xticks(rotation=45)
plt.show()
coluna = df_clientes_cadastrados_ID_unicos['Rendimento_Anual']

coluna_media = coluna.mean()
coluna_std  = coluna.std()

limite_sup = coluna_media + 2 * coluna_std
limite_inf = coluna_media - 2 * coluna_std

index_outliers = []

for index, valor in coluna.items():
  if valor > limite_sup or valor < limite_inf:
    index_outliers.append(index)

len(index_outliers)
df_clientes_cadastrados_sem_outliers = df_clientes_cadastrados_ID_unicos.drop(index_outliers)
df_clientes_cadastrados_sem_outliers.shape
df_clientes_cadastrados_sem_outliers.describe()
sns.histplot(data=df_clientes_cadastrados_sem_outliers, x='Rendimento_Anual', bins=10)
plt.xticks(rotation=45)
plt.show()
sns.histplot(data=df_clientes_cadastrados_sem_outliers, x='Idade', bins=10)
plt.xticks(rotation=45)
plt.show()
sns.histplot(data=df_clientes_cadastrados_sem_outliers.query('Anos_empregado > 0'), x='Anos_empregado')
plt.xticks(rotation=45)
plt.show()<jupyter_output><empty_output><jupyter_text>Aula 2.3<jupyter_code>df_clientes_cadastrados_sem_outliers.info()
colunas_categoricas = ['Genero'           ,      'Tem_Casa_Propria',
                       'Categoria_de_renda', 'Grau_Escolaridade',          'Estado_Civil',
                       'Moradia'           , 'Tem_Celular'      , 'Tem_telefone_trabalho', 
                       'Tem_telefone_fixo' , 'Tem_email'        , 'Ocupacao']       
df_clientes_cadastrados_sem_outliers.columns
sns.countplot(data=df_clientes_cadastrados_sem_outliers, x='Estado_Civil')
plt.xticks(rotation=45, ha='right')
plt.show()
sns.countplot(data=df_clientes_cadastrados_sem_outliers, x='Tem_Celular')
plt.xticks(rotation=45, ha='right')
plt.show()
sns.countplot(data=df_clientes_cadastrados_sem_outliers, x='Ocupacao')
plt.xticks(rotation=45, ha='right')
plt.show()
sns.histplot(data=df_clientes_cadastrados_sem_outliers.query('Ocupacao == "Outros"'), x='Rendimento_Anual', bins=10)
plt.xticks(rotation=45, ha='right')
plt.show()
df_clientes_cadastrados_tratamento1 = df_clientes_cadastrados_sem_outliers.drop(['Genero', 'Tem_Celular'], axis=1)
df_clientes_cadastrados_tratamento1.shape
colunas_categoricas.remove('Genero')
colunas_categoricas.remove('Tem_Celular')
colunas_categoricas<jupyter_output><empty_output><jupyter_text>Aula 3  Aula 3.1<jupyter_code>df_clientes_aprovados = pd.read_csv('https://raw.githubusercontent.com/HenriqueCCdA/bootCampAluraDataScience/master/modulo6/Dados/clientes_aprovados.csv')
df_clientes_aprovados.head(10)
df_clientes_aprovados.info()
df_clientes_aprovados.ID_Cliente.value_counts()
df_clientes_cadastrados_tratamento1.shape
df_clientes_aprovados.query('ID_Cliente == 5001712')
df_clientes_aprovados.query('ID_Cliente == 5001711')
df_clientes_aprovados.Faixa_atraso.value_counts().index.to_list()<jupyter_output><empty_output><jupyter_text>Aula 3.2<jupyter_code>df_registro_creditos_agrupados_ID = df_clientes_aprovados.groupby('ID_Cliente')
ser_abertura = df_registro_creditos_agrupados_ID.apply(lambda x: min(x['Mes_referencia']))
ser_abertura.name = 'Abertura'
ser_abertura
df_clientes_aprovados = df_clientes_aprovados.merge(ser_abertura, on='ID_Cliente')
df_clientes_aprovados.head(n=5)
ser_final = df_registro_creditos_agrupados_ID.apply(lambda x: max(x['Mes_referencia']))
ser_final.name = 'Final'
ser_final
df_clientes_aprovados = df_clientes_aprovados.merge(ser_final, on='ID_Cliente')
df_clientes_aprovados.head(n=5)
df_clientes_aprovados['Janela'] = df_clientes_aprovados['Final'] - df_clientes_aprovados['Abertura']
df_clientes_aprovados.head()
df_clientes_aprovados['MOB'] = df_clientes_aprovados['Mes_referencia'] - df_clientes_aprovados['Abertura']
df_clientes_aprovados.head()
dict_faixa_atraso_ind ={'nenhum empréstimo': 0, 'pagamento realizado': 1,
                        '1-29 dias': 2, '30-59 dias': 3, '60-89 dias': 4,
                        '90-119 dias': 5, '120-149 dias': 6, '>150 dias': 7}
df_clientes_aprovados['Ind_Faixa_atraso'] = df_clientes_aprovados['Faixa_atraso'].map(dict_faixa_atraso_ind)
df_clientes_aprovados.head()
df_clientes_aprovados['Mau'] = df_clientes_aprovados.apply(lambda x: 1 if x['Ind_Faixa_atraso'] > 3 else 0, axis=1)
df_clientes_aprovados.head(n=10)<jupyter_output><empty_output><jupyter_text>Aula 3.3<jupyter_code>df_registros_creditos_ID = df_clientes_aprovados[['ID_Cliente','Abertura', 'Final', 'Janela']].groupby('ID_Cliente').apply(lambda x: x.iloc[0]).reset_index(drop=True)
df_registros_creditos_ID
df_denominador = df_registros_creditos_ID.groupby('Abertura').apply(lambda X: X['ID_Cliente'].count()).reset_index()
df_denominador.columns = ['Abertura','Qtd_Clientes']
df_denominador
df_vintage = df_clientes_aprovados.groupby(['Abertura','MOB']).apply(lambda X: X['ID_Cliente'].count()).reset_index()
df_vintage.columns = ['Abertura','MOB','Qtd_Clientes']
df_vintage
df_vintage = pd.merge(df_vintage[['Abertura','MOB']], df_denominador, on = ['Abertura'], how = 'left')
df_vintage
import numpy as np
df_vintage['Qtd_Mau'] = np.nan

for j in range(-60,1):
    ls = []
    for i in range(0,61):
        due = list(df_clientes_aprovados.query('Mau == 1 and MOB == @i and Abertura == @j')['ID_Cliente'])
        ls.extend(due)
        df_vintage.loc[(df_vintage['MOB'] == i) & (df_vintage['Abertura'] == j), 'Qtd_Mau'] = len(set(ls))
        
df_vintage['Taxa_de_Mau']  = df_vintage['Qtd_Mau'] / df_vintage['Qtd_Clientes']
df_vintage
df_vintage_pivot = df_vintage.pivot(index='Abertura',
                                    columns='MOB',
                                    values='Taxa_de_Mau')
df_vintage_pivot
lst = [i for i in range(0,61)]
df_vintage_pivot[lst].T.iloc[:,:10].plot(legend = True, grid = True, title = '% acumulado de maus clientes (Atraso > que 60 dias)')

plt.xlabel('MOB')
plt.ylabel('% acumulado de maus')
plt.legend(bbox_to_anchor=(1.2, 1), title='Abertura')
plt.show()
sns.histplot(data=df_registros_creditos_ID, x='Janela', cumulative=True, stat='density', kde=True)
plt.title('Distribuição de clientes por janela')
plt.xlabel('Janela')
plt.ylabel('Percentual de clientes')
plt.show()
dict_intervalo_atraso = {'maior_30_dias': 3, 'maior_60_dias': 4, 'maior_90_dias': 5,
                        'maior_120_dias': 6, 'maior_150_dias': 7}
for chave, valor in dict_intervalo_atraso.items():
  df_clientes_aprovados[f'Mau_{chave}'] = df_clientes_aprovados.apply(lambda x: 1 if x['Ind_Faixa_atraso'] >= valor else 0, axis=1) # mais de 60
df_clientes_aprovados.head()
dict_taxa_mau = {}
id_sum = len(set(df_clientes_aprovados['ID_Cliente']))

for chave in dict_intervalo_atraso.keys():
  df_min_mau = df_clientes_aprovados.query(f'Mau_{chave} == 1').groupby('ID_Cliente')['MOB'].min().reset_index()
  df_mob_taxa_mau = pd.DataFrame({'MOB':range(0,61), 'Taxa_Mau': np.nan})
  lst = []
  for i in range(0,61):
      due = df_min_mau.query('MOB == @i')['ID_Cliente'].to_list()
      lst.extend(due) #cumsum
      df_mob_taxa_mau.loc[df_mob_taxa_mau['MOB'] == i, 'Taxa_Mau'] = len(set(lst)) / id_sum
  dict_taxa_mau[chave] = df_mob_taxa_mau['Taxa_Mau']

df_taxa_mau = pd.DataFrame(dict_taxa_mau)
df_taxa_mau
df_taxa_mau.plot(grid = True, title = '% acumulado de clientes maus para diversas faixas de atraso', figsize=(10, 6))
plt.xlabel('MOB')
plt.ylabel('% acumulado de clientes')
plt.show()<jupyter_output><empty_output><jupyter_text>Aula 3.4<jupyter_code>df_clientes_aprovados.head()
len(df_clientes_aprovados.query('Janela >= 12').groupby('ID_Cliente').count().index)
df_clientes_aprovados_tratamento1 = df_clientes_aprovados.query('Janela >= 12').copy()
df_clientes_aprovados_tratamento1.shape
def verifica(registros):
  lista_status = registros['Faixa_atraso'].to_list()
  if '60-89 dias' in lista_status or '90-119 dias' in lista_status or '120-149 dias' in lista_status or '>150 dias' in lista_status:
    return 1
  else:
    return 0
  
df_registros_creditos_id = pd.DataFrame(df_clientes_aprovados_tratamento1.groupby('ID_Cliente').apply(verifica)).reset_index()
df_registros_creditos_id.columns = ['ID_Cliente', 'Mau']
df_registros_creditos_id.head()
df_registros_creditos_id.shape
df_clientes_cadastrados_tratamento1.shape
df_registro_clientes_targets = df_clientes_cadastrados_tratamento1.merge(df_registros_creditos_id, on='ID_Cliente')
df_registro_clientes_targets.head()
df_registro_clientes_targets.shape
df_registro_clientes_targets['Mau'].value_counts(normalize=True) * 100<jupyter_output><empty_output><jupyter_text>Aula 4  Aula 4.1<jupyter_code>colunas_categoricas_binarias = ['Tem_Carro',
                                'Tem_Casa_Propria',
                                'Tem_telefone_trabalho',
                                'Tem_telefone_fixo',
                                'Tem_email']             

colunas_categoricas_binarias
colunas_categoricas_nao_binarias = ['Categoria_de_renda',
                                    'Grau_Escolaridade',
                                    'Estado_Civil',
                                    'Moradia',
                                    'Ocupacao']

colunas_categoricas_nao_binarias
df_registro_clientes_targets = df_registro_clientes_targets[['ID_Cliente'] + colunas_quantitativas + colunas_categoricas_binarias + colunas_categoricas_nao_binarias + ['Mau']]
df_registro_clientes_targets.head()
!pip install scikit-learn==0.23.2 imbalanced-learn==0.7.0
import six
import sys
sys.modules['sklearn.externals.six'] = six
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.dummy import DummyClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, classification_report, plot_confusion_matrix

from scipy import stats
SEED = 1561651
def roda_modelo(modelo, dados):

    # separando dados em x e y, e tambem removendo a coluna de ID_cliente
    x = dados.drop(['ID_Cliente', 'Mau'], axis=1)
    y = dados.drop('ID_Cliente', axis=1)['Mau']
    
    # Separando dados em treino e teste
    x_train, x_test, y_train, y_test = train_test_split(x, y, stratify=y, random_state=SEED)

    # Treinando modelo com os dados de treino
    modelo.fit(x_train, y_train)

    # Calculando a probabilidade e calculando o AUC
    prob_predic = modelo.predict_proba(x_test)
    auc = roc_auc_score(y_test, prob_predic[:,1])
    print(f"AUC {auc}")
    
    # Separando a probabilidade de ser bom e mau, e calculando o KS
    data_bom = np.sort(modelo.predict_proba(x_test)[:, 1])
    data_mau = np.sort(modelo.predict_proba(x_test)[:, 0])
    kstest = stats.ks_2samp(data_bom, data_mau)
    print(f"KS {kstest}")

    # Criando matriz de confusão
    matriz_confusao = plot_confusion_matrix(modelo, x_test, y_test, values_format='.0f', display_labels=['Bons', 'Maus'])
    plt.grid(False)    
    plt.show(matriz_confusao)

    # Fazendo a predicao dos dados de teste e calculando o classification report
    predicao = modelo.predict(x_test)
    print("\nClassification Report")
    print(classification_report(y_test, predicao, zero_division=0))
from sklearn.preprocessing import OneHotEncoder, MinMaxScaler
from sklearn.base import BaseEstimator, TransformerMixin
# PEP8 padrão CamelCase
class Transformador(BaseEstimator, TransformerMixin):
    def __init__( self, colunas_quantitativas, colunas_categoricas):
        self.colunas_quantitativas = colunas_quantitativas
        self.colunas_categoricas = colunas_categoricas
        self.enc = OneHotEncoder()
        self.scaler = MinMaxScaler()

    def fit(self, X, y = None ):
        self.enc.fit(X[self.colunas_categoricas])
        self.scaler.fit(X[self.colunas_quantitativas])
        return self 

    def transform(self, X, y = None):
      
      X_categoricas = pd.DataFrame(data=self.enc.transform(X[self.colunas_categoricas]).toarray(),
                                  columns= self.enc.get_feature_names(self.colunas_categoricas))
      
      X_continuas = pd.DataFrame(data=self.scaler.transform(X[self.colunas_quantitativas]),
                                  columns= self.colunas_quantitativas)
      
      X = pd.concat([X_continuas, X_categoricas], axis=1)

      return X
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
                    ('Transformador', Transformador(colunas_quantitativas, colunas_categoricas)),
                    ('Modelo', DummyClassifier(strategy='prior'))    
                    ])
roda_modelo(pipeline, df_registro_clientes_targets)
pipeline = Pipeline([
                    ('Transformador', Transformador(colunas_quantitativas, colunas_categoricas)),
                    ('Modelo', LogisticRegression(random_state=SEED, max_iter=1000))    
                    ])
roda_modelo(pipeline, df_registro_clientes_targets)<jupyter_output>AUC 0.5856570314973921
KS Ks_2sampResult(statistic=1.0, pvalue=0.0)<jupyter_text>Aula 4.2<jupyter_code>from imblearn.over_sampling import SMOTE
from imblearn.pipeline import Pipeline
pipeline = Pipeline([
                    ('Transformador', Transformador(colunas_quantitativas, colunas_categoricas)),
                    ('Sampling'     , SMOTE(random_state=SEED)),
                    ('Modelo'       , LogisticRegression(random_state=SEED, max_iter=1000))    
                    ])
roda_modelo(pipeline, df_registro_clientes_targets)
from sklearn.ensemble import RandomForestClassifier

pipeline = Pipeline([
                    ('Transformador', Transformador(colunas_quantitativas, colunas_categoricas)),
                    ('Modelo'       , RandomForestClassifier(random_state=SEED))    
                    ])
roda_modelo(pipeline, df_registro_clientes_targets)
pipeline = Pipeline([
                    ('Transformador', Transformador(colunas_quantitativas, colunas_categoricas)),
                    ('Sampling'     , SMOTE(random_state=SEED)),
                    ('Modelo'       , RandomForestClassifier(random_state=SEED))    
                    ])
roda_modelo(pipeline, df_registro_clientes_targets)<jupyter_output>AUC 0.8212241561380089
KS Ks_2sampResult(statistic=0.9630671825536405, pvalue=0.0)<jupyter_text>Aula 5  Aula 5.1<jupyter_code>pipeline = Pipeline([
                    ('Transformador', Transformador(colunas_quantitativas, colunas_categoricas)),
                    ('Sampling'     , SMOTE(random_state=SEED)),
                    ('Modelo'       , RandomForestClassifier(random_state=SEED))    
                    ])
df_registro_clientes_targets.head()
x = df_registro_clientes_targets.drop(['ID_Cliente', 'Mau'], axis=1)
y = df_registro_clientes_targets['Mau']

pipeline.fit(x, y)
from joblib import dump
dump(pipeline, 'modelo.joblib')
features = x.columns
features
dump(features, 'features.joblib')
lista_campos = df_registro_clientes_targets[colunas_categoricas_nao_binarias].apply(lambda x: x.unique(), axis=0)                                                                                    
lista_campos<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11335341936217384, 'fraction_numerical': 0.025297026888749928, 'mean_word_length': 4.49063670411985, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 56, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '316668', 'license': 'MIT', 'n_tokens_mistral': 7024, 'n_tokens_neox': 6626, 'n_words': 907, 'path': 'modulo6/aulas/boot_camp_modulo6_aulas.ipynb', 'repo_name': 'HenriqueCCdA/bootCampAluraDataScience', 'size': '17591'}