<jupyter_start><jupyter_text>Carregando os datasets<jupyter_code>df1 = pd.read_csv('ACCOUNTS.csv')
df2 = pd.read_csv('DEMOGRAPHICS.csv')
df3 = pd.read_csv('LOANS.csv')<jupyter_output><empty_output><jupyter_text>Visão GeralCompreender cada informação coletada é essencial para um possível modelo que será gerado. Nesse sentido, gera-se uma análise inicial de cada variável (ou coluna) coletada e justifica-se o porquê de certas variáveis não serem consideradas no modelo ou até mesmo, qual tratamento de dados será utilizado nela.<jupyter_code>df1.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 2477 entries, 0 to 2476
Data columns (total 5 columns):
 #   Column                  Non-Null Count  Dtype  
---  ------                  --------------  -----  
 0   ID                      2477 non-null   int64  
 1   CHECKING_BALANCE        2467 non-null   object 
 2   CREDIT_HISTORY          2462 non-null   object 
 3   EXISTING_SAVINGS        2467 non-null   object 
 4   EXISTING_CREDITS_COUNT  2463 non-null   float64
dtypes: float64(1), int64(1), object(3)
memory usage: 96.9+ KB<jupyter_text>A função info() mostra um resumo geral do comportamento dos dados, apesar de superficial é possível observar que os dados estão desbalanceados, ou seja, será necessário realizar uma análise exploratória individual de cada variável. Além disso, será necessário efetuar um tratamento e limpeza de informações com pouca relevância para o modelo de classificação que se almeja construir.  Fase 1: Análise individual de cada variável, tratamento de dados, junção das bases de dados, análise de outliers.  - Análise Inicial de Dados 1 - 'accounts.csv'<jupyter_code>df1
df1.corr() 
df1[df1['CHECKING_BALANCE']=='NO_CHECKING']
df1[df1['EXISTING_SAVINGS']=='UNKNOWN']<jupyter_output><empty_output><jupyter_text>1) Com relação aos saldo da conta de cada cliente, qual a relação entre verificados e não verificados?<jupyter_code># Dividi-se o dataset em 2, onde a variável check é compreendida pelas informações numéricas.
no_check = len(df1[df1[u'CHECKING_BALANCE'] == 'NO_CHECKING'])
check = len(df1[df1[u'CHECKING_BALANCE'] != 'NO_CHECKING'])

new_df = {'NO_CHECKING': [no_check], 'CHECKING': [check]}

checking_balance = pd.DataFrame(data=new_df)
sns.set(style="darkgrid")

fig = sns.barplot(x=list(checking_balance) ,y=[checking_balance['CHECKING'].iloc[0],checking_balance['NO_CHECKING'].iloc[0]],hue=list(checking_balance))
plt.title("Relação entre saldos verificados e não verificados")
plt.show(fig)<jupyter_output><empty_output><jupyter_text>2) Quais características estão presentes na coluna 'Histórico de Crédito'?<jupyter_code>df1['CREDIT_HISTORY'].unique()<jupyter_output><empty_output><jupyter_text>3) Qual a relação entre economias conhecidas e desconhecidas dos clientes com o banco?<jupyter_code># Dividi-se o dataset em 2, onde a variável check é compreendida pelas informações numéricas.
exis = len(df1[df1[u'EXISTING_SAVINGS'] != 'UNKNOWN'])
no_exis = len(df1[df1[u'EXISTING_SAVINGS'] == 'UNKNOWN'])

new_df2 = {'EXISTING_SAVINGS': [exis], 'NO_EXISTING_SAVINGS': [no_exis]}

check_savings = pd.DataFrame(data=new_df2)
check_savings
sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_savings) ,y=[check_savings['EXISTING_SAVINGS'].iloc[0],
                                            check_savings['NO_EXISTING_SAVINGS'].iloc[0]],
                                            hue=list(check_savings))
plt.title("Relação entre saldos verificados e não verificados")
plt.show(fig)
df1[df1['EXISTING_CREDITS_COUNT'].isnull()]<jupyter_output><empty_output><jupyter_text>-  Análise Inicial de Dados 2 - 'demographics.csv'<jupyter_code>df2
df2.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 3936 entries, 0 to 3935
Data columns (total 11 columns):
 #   Column                      Non-Null Count  Dtype  
---  ------                      --------------  -----  
 0   ID                          3936 non-null   int64  
 1   SEX                         3920 non-null   object 
 2   AGE                         3918 non-null   float64
 3   JOB_TYPE                    3910 non-null   float64
 4   DEPENDENTS                  3915 non-null   float64
 5   TELEPHONE                   3915 non-null   float64
 6   FOREIGN_WORKER              3909 non-null   float64
 7   EMPLOYMENT_DURATION         3923 non-null   float64
 8   PROPERTY                    3918 non-null   object 
 9   HOUSING                     3912 non-null   object 
 10  CURRENT_RESIDENCE_DURATION  3917 non-null   float64
dtypes: float64(7), int64(1), object(3)
memory usage: 338.4+ KB<jupyter_text>Qual o sexo dos clientes?<jupyter_code>df2['SEX'].value_counts()
df2['SEX'].fillna("NR", inplace = True)
# Dividi-se o dataset em 2, onde a variável check é compreendida pelas informações numéricas.
sex_M = len(df2[df2[u'SEX'] == 'M'])
sex_F = len(df2[df2[u'SEX'] == 'F'])
sex_NR = len(df2[df2[u'SEX'] == 'NR']) # não respondido (NaN)

new_df2 = {'M': [sex_M], 'F': [sex_F]}

check_sex = pd.DataFrame(data=new_df2)
sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_sex),
                  y=[check_sex['M'].iloc[0],
                     check_sex['F'].iloc[0]],
                     hue=list(check_sex))
plt.grid(None)
plt.title("Relação entre gênero")
plt.rcParams["figure.figsize"] = (4,6)
plt.show(fig)<jupyter_output><empty_output><jupyter_text>Nesse caso, baseado nos dados optamos por apenas apresentar a relação entre o sexo Masculino e Feminino para informações bancárias. Vale ressaltar que o índice percentual de pessoas que ou não responderam, ou que por alguma instabilidade do sistema não foi salva é de 0.4% no total (16 registros sem resposta). Todavia isso não é tudo, é importante entender também qual amostra está a nossa disposição, no caso, temos um total de 3936 dados.  Qual a distribuição a cerca da idade dos nossos clientes?Para auxiliar nessa tarefa, criamos alguns filtros para compreender melhor a qual faixa etária os clientes da BanTotal pertencem.<jupyter_code>#df2['AGE'].value_counts()
ax = sns.distplot(df2.AGE, kde = False, 
                  bins = [i*5 for(i) in range (15)])
ax.set_xlabel("Idade das pessoas", 
              fontsize = 20, 
              position=(0.5,0))

ax.set_ylabel("Quantidade de pessoas", 
              fontsize = 20, 
              position=(0.5,0.5))

ax.grid(None)

ax.set_title('Distribuição do número de pessoas', 
             fontsize = 20)

ax.figure.set_size_inches(12,8)<jupyter_output><empty_output><jupyter_text>Qual a distribuição que indica quantos dependentes nossos clientes têm?<jupyter_code>df2['DEPENDENTS'].value_counts()
dep1 = len(df2[df2[u'DEPENDENTS'] == 1.0])
dep2 = len(df2[df2[u'DEPENDENTS'] == 2.0])

new_df3 = {'1.0': [dep1], '2.0': [dep2]}

check_dependence = pd.DataFrame(data=new_df3)
check_dependence
sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_dependence),
                  y=[check_dependence['1.0'].iloc[0],
                     check_dependence['2.0'].iloc[0]],
                     hue=list(check_dependence))
plt.grid(None)
plt.title("Relação entre dependentes")
plt.rcParams["figure.figsize"] = (4,6)
plt.show(fig)<jupyter_output><empty_output><jupyter_text>O cliente tem telefone registrado no sistema?0 - não1 - sim<jupyter_code>df2['TELEPHONE'].value_counts()
phone1 = len(df2[df2[u'TELEPHONE'] == 0.0])
phone2 = len(df2[df2[u'TELEPHONE'] == 1.0])

new_df4 = {'Sim': [phone1], 'Não': [phone2]}

check_phone = pd.DataFrame(data=new_df4)
sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_phone),
                  y=[check_phone['Sim'].iloc[0],
                     check_phone['Não'].iloc[0]],
                     hue=list(check_phone))
plt.grid(None)
plt.title("O cliente tem telefone registrado no sistema?")
plt.rcParams["figure.figsize"] = (6,8)
plt.show(fig)<jupyter_output><empty_output><jupyter_text>O cliente é um trabalhador estrangeiro?<jupyter_code>df2['FOREIGN_WORKER'].value_counts()
w1 = len(df2[df2[u'FOREIGN_WORKER'] == 0.0])
w2 = len(df2[df2[u'FOREIGN_WORKER'] == 1.0])

new_df4 = {'Sim': [w2], 'Não': [w1]}

check_worker = pd.DataFrame(data=new_df4)
sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_worker),
                  y=[check_worker['Sim'].iloc[0],
                     check_worker['Não'].iloc[0]],
                     hue=list(check_worker))
plt.grid(None)
plt.title("O cliente tem telefone registrado no sistema?")
plt.rcParams["figure.figsize"] = (6,8)
plt.show(fig)<jupyter_output><empty_output><jupyter_text>Duração do Trabalho<jupyter_code>df2['EMPLOYMENT_DURATION'].value_counts()
ax = sns.distplot(df2.EMPLOYMENT_DURATION, kde = False, 
                  bins = [i for(i) in range (17)])

ax.set_xlabel("Duração de Trabalho", 
              fontsize = 20, 
              position=(0.5,0))

ax.set_ylabel("Quantidade de pessoas", 
              fontsize = 20, 
              position=(0.5,0.5))

ax.grid(None)

ax.set_title('Distribuição da duração de trabalho', 
             fontsize = 20)

ax.figure.set_size_inches(12,8)<jupyter_output><empty_output><jupyter_text>Propriedade<jupyter_code>df2['PROPERTY'].unique()<jupyter_output><empty_output><jupyter_text>Habitação<jupyter_code>df2['HOUSING'].unique()<jupyter_output><empty_output><jupyter_text>Duração de Residência Atual<jupyter_code>df2['CURRENT_RESIDENCE_DURATION'].value_counts()
crd1 = len(df2[df2[u'FOREIGN_WORKER'] == 1.0])
crd2 = len(df2[df2[u'CURRENT_RESIDENCE_DURATION'] == 2.0])
crd3 = len(df2[df2[u'CURRENT_RESIDENCE_DURATION'] == 3.0])
crd4 = len(df2[df2[u'CURRENT_RESIDENCE_DURATION'] == 4.0])
crd5 = len(df2[df2[u'CURRENT_RESIDENCE_DURATION'] == 5.0])
crd6 = len(df2[df2[u'CURRENT_RESIDENCE_DURATION'] == 6.0])

new_df5 = {'1': [crd1], '2': [crd2], '3': [crd3], '4': [crd4], '5': [crd5], '6': [crd6]}

check_crd = pd.DataFrame(data=new_df5)
sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_crd),
                  y=[check_crd['1'].iloc[0],
                     check_crd['2'].iloc[0],
                     check_crd['3'].iloc[0],
                     check_crd['4'].iloc[0],
                     check_crd['5'].iloc[0],
                     check_crd['6'].iloc[0]],
                     hue=list(check_crd))
plt.grid(None)
plt.title("O cliente tem telefone registrado no sistema?")
plt.rcParams["figure.figsize"] = (12,12)
plt.show(fig)<jupyter_output><empty_output><jupyter_text>Questão x: De acordo com os insights obtidos nas questões anteriores, quais serão as decisões de tratamento a serem adotadas nos dados?  - Análise Inicial de Dados 3 - 'LOANS.csv'<jupyter_code>df3<jupyter_output><empty_output><jupyter_text>Esse dataset é composto por informações amplamente correlacionadas a uma possível concessão de crédito para os clientes da BanTotal. Cada cliente é identificado por uma chave ID e também há outras variávéis como: Termo de Pagamento, Percentual de Parcelamento, Objetivo do Empréstimo, Montante do Empréstimo, Outros Empréstimos, Permitir. Mas fique atento, apenas a leitura superficial das colunas do conjunto de dados não é suficiente para tirar conclusões ou sair aplicando funções de limpeza de dados, é importante estudar individualmente cada variável e formular hipóteses de como remodelar essa variável para contribuir para o modelo que será construído. Um exemplo disso são as variáveis categóricas (não numéricas) contidas no conjunto de dados acima.  Termo de Pagamento<jupyter_code>df3.PAYMENT_TERM
ax = sns.distplot(df3.PAYMENT_TERM, kde = False)

ax.set_xlabel("Termo de Pagamento", 
              fontsize = 20, 
              position=(0.5,0))

ax.set_ylabel("Clientes", 
              fontsize = 20, 
              position=(0.5,0.5))

ax.grid(None)

ax.set_title('Distribuição da duração de trabalho', 
             fontsize = 20)

ax.figure.set_size_inches(20,18)<jupyter_output><empty_output><jupyter_text>Planos de Parcelamento<jupyter_code>df3['INSTALLMENT_PLANS'].unique()<jupyter_output><empty_output><jupyter_text>Percentual de Parcelamento<jupyter_code>ax = sns.distplot(df3.INSTALLMENT_PERCENT, kde = False)

ax.set_xlabel("Percentual de Parcelamento", 
              fontsize = 20, 
              position=(0.5,0))

ax.set_ylabel("Clientes", 
              fontsize = 20, 
              position=(0.5,0.5))

ax.grid(None)

ax.set_title('Distribuição de Percentual de Parcelamento', 
             fontsize = 20)

ax.figure.set_size_inches(5,5)<jupyter_output><empty_output><jupyter_text>Objetivo do Empréstimo<jupyter_code>aux = df3['LOAN_PURPOSE'].value_counts()
aux
result = []
for i in range(len(df3['LOAN_PURPOSE'].value_counts())):
    result.append(aux[i])
result
# Note que não conseguimos manipular as linhas apresentadas no objeto series gerado pela função .value_counts()
# Para solucionar, transformamos esse objeto series em um dataframe e listamos os seus índices
aux2 = pd.DataFrame(aux)
montantes = list(aux2.index)
montantes
# Plota-se o gráfico entre os tipos de objetivo de empréstimo e quantidade de clientes
plt.rcParams["figure.figsize"] = (8,7)
plt.barh(montantes, result, color='blue')<jupyter_output><empty_output><jupyter_text>Montante do Empréstimo<jupyter_code>ax = sns.distplot(df3.LOAN_AMOUNT, kde = False)

ax.set_xlabel("Percentual de Parcelamento", 
              fontsize = 20, 
              position=(0.5,0))

ax.set_ylabel("Clientes", 
              fontsize = 20, 
              position=(0.5,0.5))

ax.grid(None)

ax.set_title('Distribuição do Montante do Empréstimo', 
             fontsize = 20)

ax.figure.set_size_inches(12,10)<jupyter_output><empty_output><jupyter_text>Outros Empréstimos Ativos<jupyter_code>aux = df3['OTHERS_ON_LOAN'].value_counts()
result = []
for i in range(len(df3['OTHERS_ON_LOAN'].value_counts())):
    result.append(aux[i])

aux2 = pd.DataFrame(aux)
others = list(aux2.index)

plt.rcParams["figure.figsize"] = (4,3)
plt.barh(others, result, color='blue')<jupyter_output><empty_output><jupyter_text>Permitir Empréstimo?Essa é variável no qual pretende-se classificar com a entrada de novos clientes. De forma objetiva, ela só pode retornar dois possíveis valores: 0 caso o modelo indique que o empréstimo não será concedido, e 1 caso o empréstimo será concedido.<jupyter_code>yes = len(df3[df3[u'ALLOW'] == 1])
no = len(df3[df3[u'ALLOW'] == 0])

new_df = {'Permitir': [yes], 'Não Permitir': [no]}

check_allow = pd.DataFrame(data=new_df)

sns.set(style="darkgrid")

fig = sns.barplot(x=list(check_allow),
                  y=[check_allow['Permitir'].iloc[0],
                     check_allow['Não Permitir'].iloc[0]],
                     hue=list(check_allow))
plt.grid(None)
plt.title("Qual decisão empréstimo foi aprovado?")
plt.rcParams["figure.figsize"] = (6,8)
plt.show(fig)<jupyter_output><empty_output><jupyter_text>Visão GeralCompreender cada variável é uma etapa importante no processo da resolução do problema, pois, caso optemos por adicionar, tratar ou remover uma variável do modelo que será treinado e testado, é de suma importância entender o que essa variável representa e por qual razão foi tomada uma determinada decisão em relação a ela. Dessa maneira você receberá insights valiosos para a criação da sua narrativa para storytelling de dados.Todavia isso não é tudo, na próxima seção será construído o tratamento de dados ausentes, variáveis categóricas e uma análise exploratória juntando as bases de dados através do Pandas.  Tratamento de DadosO tratamento de dados pode ser construídos de 2 formas, a primeira trataria variáveis categóricas associadas a um id como 0 ou 1, seguindo a lógica de um "One Hot Encoder". Outra maneira, seria determinar índices associados a uma determinada variável categórica como, por exemplo: 0 - não informado, 1 - ruim, 2 - médio, 3 - bom.  Tratamento de Dados 1 - Preparando a variável categórica 'histórico de crédito' para o modelo de classificação  Juntando dataframes a partir do ID<jupyter_code>df = pd.merge(pd.merge(df1,df2,on='ID'),df3,on='ID')
df<jupyter_output><empty_output><jupyter_text>Observe que ao unir as bases de dados de clientes, uma nova análise pode ser construída, pois, nessa nova etapa buscaremos compreender quais as correlações entre variáveis de diferentes bases se relacionam e claro, como essas variáveis influenciam a concessão de empréstimo a clientes ou não.<jupyter_code>df.info()
df = df.fillna(method="ffill") # tratamento dos dados
df.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
Int64Index: 2477 entries, 0 to 2476
Data columns (total 22 columns):
 #   Column                      Non-Null Count  Dtype  
---  ------                      --------------  -----  
 0   ID                          2477 non-null   int64  
 1   CHECKING_BALANCE            2477 non-null   object 
 2   CREDIT_HISTORY              2477 non-null   object 
 3   EXISTING_SAVINGS            2477 non-null   object 
 4   EXISTING_CREDITS_COUNT      2477 non-null   float64
 5   SEX                         2477 non-null   object 
 6   AGE                         2477 non-null   float64
 7   JOB_TYPE                    2477 non-null   float64
 8   DEPENDENTS                  2477 non-null   float64
 9   TELEPHONE                   2477 non-null   float64
 10  FOREIGN_WORKER              2477 non-null   float64
 11  EMPLOYMENT_DURATION         2477 non-null   float64
 12  PROPERTY                    2477 non-null   object 
 13  HOUSING                     2477 [...]<jupyter_text>Criamos uma função simples para retornar um dataframe com as correlações das variáveis de estudo<jupyter_code>def update_corr(df):
    result_corr = df.corr().sort_values(by='ALLOW')
    result_corr = result_corr['ALLOW']

    return result_corr
update_corr(df) # testando função<jupyter_output><empty_output><jupyter_text>Observe que nove variáveis não apareceram na tabela de correlação mostrada anteriormente devido a necessidade de um tratamento de dados específico como, por exemplo, as variáveis categóricas.<jupyter_code>enc = OneHotEncoder(cols=['CREDIT_HISTORY', 'SEX', 'PROPERTY','HOUSING','LOAN_PURPOSE','OTHERS_ON_LOAN','INSTALLMENT_PLANS'], use_cat_names=True)
enc.fit(df)
df = enc.transform(df)
df<jupyter_output><empty_output><jupyter_text>Observe que as variáveis 'CHECKING_BALANCE ' e 'EXISTING_SAVINGS' ainda não foram tratadas, qual procedimento será realizado?Com relação a variável 'CHECKING_BALANCE' uma das alternativas seria excluir todos os dados de contas que não tiveram seus balanços verificados, entretanto o conjunto de dados seria reduzido em aproximadamente 40% (de 2477 para 1485 dados), o que é um valor considerável tendo em vista que eliminar tantos dados reduziria a futura precisão do nosso modelo.<jupyter_code>af = df[~df['CHECKING_BALANCE'].isin(['NO_CHECKING'])] # excluindo todos os registros de contas com balanço não verificado
len(af) # tamanho do novo dataset, caso seja aprovado<jupyter_output><empty_output><jupyter_text>Uma alternativa seria transformar os dados numéricos em 4 tipos de informação:- NEGATIVE: Compreende todas as contas com saldo negativo;- ZERO: Compreende todas as contas zeradas;- POSITIVE: Compreende todas as contas com saldo positivo;- NO_CHECKING: Compreende todas as contas não verificadas (já existente).Porém no momento, para fim de simplificação, opta-se por não utilizar a variável no modelo.<jupyter_code>aux = df[~df['EXISTING_SAVINGS'].isin(['UNKNOWN'])]
aux = aux.drop(columns=['CHECKING_BALANCE'])
aux = aux.apply(pd.to_numeric)
update_corr(aux) # imprime a nova tabela de correlação com a inclusão da variável 'EXISTING_SAVINGS'<jupyter_output><empty_output><jupyter_text>Observação: Como a variável 'EXISTING_SAVINGS' possui uma correlação baixa com a nossa variável objetivo, então desfazemos o último tratamento que reduziu os dados em 7% (2400 para 2300 dados). Entretanto, mantém-se a decisão de excluir a variável 'CHECKING_BALANCE'.<jupyter_code>df = df.drop(columns=['CHECKING_BALANCE'])<jupyter_output><empty_output><jupyter_text>Removendo todas colunas desnecessárias<jupyter_code>df = df[['AGE','LOAN_AMOUNT','PAYMENT_TERM','EMPLOYMENT_DURATION','CURRENT_RESIDENCE_DURATION','INSTALLMENT_PERCENT','ALLOW']]
df<jupyter_output><empty_output><jupyter_text>Análise de OutliersOutra etapa importante da análise de dados é a de identificar possíveis valores extremos ou anomalias na nossa base de dados, pois, esses valores podem comprometer o nosso modelo.  Verificando a distribuição das variáveis do conjunto de dados<jupyter_code>plt.figure(figsize=(16,5))
plt.subplot(1,3,1)
sns.distplot(df['AGE'])
plt.subplot(1,3,2)
sns.distplot(df['LOAN_AMOUNT'])
plt.subplot(1,3,3)
sns.distplot(df['PAYMENT_TERM'])
plt.show()
plt.figure(figsize=(16,5))
plt.subplot(1,3,1)
sns.distplot(df['EMPLOYMENT_DURATION'])
plt.subplot(1,3,2)
sns.distplot(df['CURRENT_RESIDENCE_DURATION'])
plt.subplot(1,3,3)
sns.distplot(df['INSTALLMENT_PERCENT'])<jupyter_output><empty_output><jupyter_text>Observando os gráficos de distribuição por variável é possível notar que elas não seguem a distribuição normal. Dessa forma a técnica que será utilizada para detectar outliers não poderá ser baseada na Z-Score. Como alternativa utiliza-se uma técnica baseada no IQR ou, em outras palavras, a amplitude interquartil.  Boxplot das variáveis<jupyter_code>plt.figure(figsize=(16,5))
plt.subplot(1,3,1)
sns.boxplot(df['AGE'])
plt.subplot(1,3,2)
sns.boxplot(df['LOAN_AMOUNT'])
plt.subplot(1,3,3)
sns.boxplot(df['PAYMENT_TERM'])
plt.figure(figsize=(16,5))
plt.subplot(1,3,1)
sns.boxplot(df['EMPLOYMENT_DURATION'])
plt.subplot(1,3,2)
sns.boxplot(df['CURRENT_RESIDENCE_DURATION'])
plt.subplot(1,3,3)
sns.boxplot(df['INSTALLMENT_PERCENT'])<jupyter_output><empty_output><jupyter_text>Observe que nem todas as variáveis têm indícios de presença de outliers. Nesse caso, aplicaremos a técnica de remoção de outliers apenas nas variáveis 'AGE', 'LOAN_AMOUNT', 'PAYMENT_TERM' e 'EMPLOYMENT_DURATION'. Obs.: Para avaliar melhor o impacto que a remoção de outliers proporciona, será realizado análise individual por variável.<jupyter_code># aplica IQR a variável 'AGE'
percentil25 = df['AGE'].quantile(0.25)
percentil75 = df['AGE'].quantile(0.75)
        
upper_limit = percentil75 + 1.5 * (percentil75-percentil25)
lower_limit = percentil25 - 1.5 * (percentil75-percentil25)

df[df['AGE'] > upper_limit]
df[df['AGE'] < lower_limit]

df = df[df['AGE'] < upper_limit]
df
# aplica IQR a variável 'LOAN_AMOUNT'

percentil25 = df['LOAN_AMOUNT'].quantile(0.25)
percentil75 = df['LOAN_AMOUNT'].quantile(0.75)
        
upper_limit = percentil75 + 1.5 * (percentil75-percentil25)
lower_limit = percentil25 - 1.5 * (percentil75-percentil25)

df[df['LOAN_AMOUNT'] > upper_limit]
df[df['LOAN_AMOUNT'] < lower_limit]

df = df[df['LOAN_AMOUNT'] < upper_limit]
df
# aplica IQR a variável 'PAYMENT_TERM'

percentil25 = df['PAYMENT_TERM'].quantile(0.25)
percentil75 = df['PAYMENT_TERM'].quantile(0.75)
        
upper_limit = percentil75 + 1.5 * (percentil75-percentil25)
lower_limit = percentil25 - 1.5 * (percentil75-percentil25)

df[df['PAYMENT_TERM'] > upper_limit]
df[df['PAYMENT_TERM'] < lower_limit]

df = df[df['PAYMENT_TERM'] < upper_limit]
df
# aplica IQR a variável 'EMPLOYMENT_DURATION'

percentil25 = df['PAYMENT_TERM'].quantile(0.25)
percentil75 = df['PAYMENT_TERM'].quantile(0.75)
        
upper_limit = percentil75 + 1.5 * (percentil75-percentil25)
lower_limit = percentil25 - 1.5 * (percentil75-percentil25)

df[df['PAYMENT_TERM'] > upper_limit]
df[df['PAYMENT_TERM'] < lower_limit]

df = df[df['PAYMENT_TERM'] < upper_limit]
df<jupyter_output><empty_output><jupyter_text>Removemos um total de 11 outliers, esse valor pode parecer baixo, entretanto, em casos de grandes volumes de dados não tratar esses dados pode dificultar o modo como os seus futuros modelos de aprendizado de máquina aprenderão.  Fase 2: Treino, Teste e Aplicação do Algoritmo de Random Forest<jupyter_code>from sklearn.ensemble import RandomForestClassifier
train, test = train_test_split(df, train_size=0.70) # dividimos o dataset em treino (70%) e teste (30%)
X_train = train.drop('ALLOW', axis=1)
X_val = test.drop('ALLOW', axis=1)

y_train = train['ALLOW']
y_val = test['ALLOW']
mdl = RandomForestClassifier(n_estimators=300, min_samples_leaf=2, random_state=0,n_jobs=-1)
mdl.fit(X_train, y_train)
p_ohe = mdl.predict(X_val)
mean_absolute_error(y_val, p_ohe)
from sklearn.metrics import r2_score
r2_score(y_val, p_ohe)
p_ohe<jupyter_output><empty_output><jupyter_text>Fase 3: Criando função para deploy do modelo<jupyter_code>def modelo_credito(df):
    allow = []
    for i in range(len(df)):
        aux = df.copy()
        aux = aux[['AGE','LOAN_AMOUNT','PAYMENT_TERM','EMPLOYMENT_DURATION','CURRENT_RESIDENCE_DURATION','INSTALLMENT_PERCENT']]
        aux = aux.iloc[i].to_numpy()[0:6]
        aux = aux.reshape(-1, 1)
        aux = aux.T
        exe = mdl.predict(aux)[0]
        allow.append(exe)
    return allow
answers = pd.read_csv('ANSWERS.csv')
answers.head()
resposta = modelo_credito(answers) # determinando variável de concessão de crédito 'ALLOW'
for i in range(len(answers)):
    answers['ALLOW'][i] = resposta[i]
answers
answers.to_csv('ANSWERS.csv')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11447704081632654, 'fraction_numerical': 0.03053252551020408, 'mean_word_length': 4.269691241335853, 'pattern_counts': {'":': 0, '<': 157, '<?xml version=': 0, '>': 153, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '37', 'dir': 'jupyter-structured-clean-dedup', 'id': '593655', 'license': 'Apache-2.0', 'n_tokens_mistral': 9818, 'n_tokens_neox': 9127, 'n_words': 2121, 'path': 'Desafio 1/Desafio 1.ipynb', 'repo_name': 'Danilosvsv/Maratona_BehindTheCode', 'size': '25088'}