Contextualização
Alguns dos assuntos mais cometados dos dias de hoje é Inteligência artificial e machine learning (ou aprendizagem de máquina). Que nada mais são do que modelos, onde a máquina aprende com informações existentes (costumamos chamar de dados).
E assim, uma vez que a máquina entende os padrões contidos nos dados, o modelo pode ser usado para previsão de valores ou, no caso, categorias.
Introdução
Para exemplificar o uso de alguns modelos de machine learning vamos pegar um dataset do kaggle de risco de crédito, vamos realizar um tratamento básico para os dados (apenas o suficiente para conseguirmos rodar os modelos) e depois usar o dataset para compararmos a acurácia de:
Regressão logística
Naive Bayes
Random Forest
XGBoost
Lembrando que o foco principal aqui, não é realizar o processo inteiro de uma análise de dados detalhadamento, apenas exemplificar o uso dos modelos com o sklearn, depois vou fazer um texto explicando cada um dos modelos, que pode ser visto na aba de texto deste mesmo site.
De maneira bem simples, modelos de classificação buscam - como o nome diz - classificar dados em classes ou categorias. Isso é um modelo de aprendizado supervisionado. Onde os dados possuem uma classe associada. Alguns exemplos de uso desses modelos:
Detecção de fraudes;
Análise de sentimentos;
Diagnósticos médicos;
Os nossos datasets reunem informações de crédito e pagamento de vários clientes, separados em duas tabelas, uma com informações dos clientes e outra com informações dos pagamentos. Basicamente vamos tentar prever a variável label, contida na tabela customer_data:
label 1, o cliente tem um alto risco de crédito;
label 0, o cliente tem um baixo risco de crédito;
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# importando nossos dataframes
customer = pd.read_csv('risk-credit/customer_data.csv')
payment = pd.read_csv('risk-credit/payment_data.csv')
customer
Vamos verificar os valores em label
# contar labels em 0 e 1
np.unique(customer['label'], return_counts = True)
E para melhorar um pouco a visualização vamos plotar isso em porcentagem:
# visualizar a separacao das informacoes
label = customer['label'].value_counts(normalize = True) * 100
sns.barplot(x=label.index, y = label.values)
Como é possível notar, a maioria dos nossos clientes tem um risco de crédito baixo (~80%). Agora, vamos verificar o tipo de valores e se existem valores null:
# verificar valores null e tipos de objetos
customer.info()
Para rodar nossos modelos vamos ter que dar um jeito nas variáveis faltantes de fea_2. Vamos dar uma olhada nos dados de payment também:
# agora vamos lidar com os dados de payment
payment.info()
Certo, aqui também temos dados faltantes em prod_limit e highest_balance. No começo do tratamento
Algumas variáveis tem uma correlação bem significativa entre si, por exemplo: fea_10 e fea_11; fea_10 e fea_7, fea_6 e fea_1. Porém, como informado anteriomente, o foco não é corrigir esses problemas no tratamento dos dados e sim rodar os modelos. Nesse caso, vamos apenas completar o dados faltantes em fea_2. Para isso, vamos utilizar o modelo simples de KNN para imputar os dados faltantes:
# para corrigir os valores faltantes em fea_2, vamos usar o model KNN
from sklearn.impute import KNNImputer
mv_impute = KNNImputer(n_neighbors= 3)
customer['fea_2'] = mv_impute.fit_transform(customer[['fea_2']])
# checando se os valores forem incluidos o código abaixo vai somar os valores que forem null
customer.isnull().sum()
Certo, também precisamos dar uma olhada nos dados de payment
# agora vamos lidar com os dados de payment
payment.info()
Certo, como também temos valores null aqui, vamos realizar as tratativas:
1 - Ba
# employment level table
tail(aggregate_pnad, 6) %>%
select(date, ocupacao) %>%
flextable() %>%
flextable::align(align='c',
part='all') %>%
flextable::width(j = 1:2,
width = 1.8) %>%
flextable::set_header_labels(date = "Período",
ocupacao = "Nível de Ocupação (%)") %>%
flextable::bold(bold = TRUE, part='header')
tail(aggregate_pnad, 6) %>%
select(date, ocupacao) %>%
kable()
# employment level graph
aggregate_pnad %>%
select(date, ocupacao) %>%
ggplot()+
aes(x = date, y = ocupacao)+
geom_line(size=0.9,
color='darkblue')+
geom_label_repel(data = filter(agregate_pnad,
date == max(date)),
aes(label = ocupacao),
vjust = 0.8,
color = 'white',
fill = 'darkblue',
fontface = 'bold')+
scale_x_date(breaks = '1 year',
labels = date_format('%Y'))+
labs(x = '',
y = '%',
title = 'Nível de ocupação (%)',
subtitle = 'População ocupada / População em idade ativa',
caption = foot)+
theme_bw()
|date | ocupacao|
|:----------|--------:|
|2022-11-01 | 57.39|
|2022-12-01 | 57.16|
|2023-01-01 | 56.70|
|2023-02-01 | 56.36|
|2023-03-01 | 56.15|
|2023-04-01 | 56.23|
Tivemos os piores níveis de ocupação durante os anos de 2020 e 2021, com o número chegando históricamente abaixo de 50% da população economicamente ativa. Depois disso, o mercado de trabalho volta a se aquecer o número de ocupação começa a subir até encontrar mais uma vez sua baixa nos últimos 5 meses, com um pequeno acréscimo de março para abril.
Passaremos agora a olhar para os dados por categoria de emprego, para isso puxaremos a tebela 4090 do Sidra:
# Dados da PNAD: categoria do emprego
## Dados da PNAD: categoria do emprego
ocupacao_categoria <-
get_sidra(api='/t/6320/n1/all/v/4090/p/all/c11913/allxt') %>%
mutate(date = parse_date(`Trimestre Móvel (Código)`,
format='%Y%m')) %>%
select(date,
`Posição na ocupação e categoria do emprego no trabalho principal`,
Valor) %>%
pivot_wider(names_from = `Posição na ocupação e categoria do emprego no trabalho principal`,
values_from = 'Valor')
Vamos analisar a evolução do emprego informal, ou seja, que não possue carteira assinada.
## without formal contracts
sem_carteira <-
ocupacao_categoria %>%
select(date, `Empregado no setor privado, exclusive trabalhador doméstico - sem carteira de trabalho assinada`) %>%
dplyr::rename('Sem carteira' = "Empregado no setor privado, exclusive trabalhador doméstico - sem carteira de trabalho assinada") %>%
mutate(`Sem carteira` = round(`Sem carteira`/1000, 2))
## table
tail(sem_carteira, 6) %>%
flextable() %>%
flextable::align(align='c',
part='all') %>%
flextable::width(j = 1:2,
width = 1.8) %>%
flextable::set_header_labels(date = "Período",
'Sem carteira' = "Sem carteira (Em milhões)") %>%
flextable::bold(bold = TRUE,
part='header')
## graph
sem_carteira %>%
ggplot()+
aes(x = date, y = `Sem carteira`)+
geom_line(size=0.9,
color='darkblue')+
geom_label_repel(data = filter(sem_carteira,
date == max(date)),
aes(label = `Sem carteira`),
vjust = 0.8,
color = 'white',
fill = 'darkblue',
fontface = 'bold')+
scale_x_date(breaks = '1 year',
labels = date_format('%Y'))+
labs(x = '',
y = 'Em milhões',
title = 'Trabalhadores sem carteira',
caption = foot)+
theme_bw()
> tail(sem_carteira, 6) %>%
+ kable()
|date | Sem carteira|
|:----------|------------:|
|2022-11-01 | 13.31|
|2022-12-01 | 13.24|
|2023-01-01 | 13.11|
|2023-02-01 | 12.96|
|2023-03-01 | 12.81|
|2023-04-01 | 12.72|
A partir de 2020 o trabalho informou aumentou consideravelmente, e apresenta diminuição no último semestre. Chegando a 12.7 milhões de pessoas no mês de referência. Na sequência veremos os dados referentes a trabalhadores por conta própria, que são aquelas que realizam atividades econômicas de maneira autônoma.
## self-employed workers
conta_propria <-
ocupacao_categoria %>%
select(date, `Conta própria`) %>%
mutate(`Conta própria` = round(`Conta própria`/1000, 2))
## table
tail(conta_propria, 6) %>%
flextable() %>%
flextable::align(align='c',
part='all') %>%
flextable::width(j = 1:2,
width = 1.8) %>%
flextable::set_header_labels(date = "Período",
'Conta própria' = "Conta própria (Em milhões)") %>%
flextable::bold(bold = TRUE,
part='header')
## graph
conta_propria %>%
ggplot()+
aes(x = date, y = `Conta própria`)+
geom_line(size=0.9,
color='darkblue')+
geom_label_repel(data = filter(conta_propria,
date == max(date)),
aes(label = `Conta própria`),
vjust = 0.8,
color = 'white',
fill = 'darkblue',
fontface = 'bold')+
scale_x_date(breaks = '1 year',
labels = date_format('%Y'))+
labs(x = '',
y = 'Em milhões',
title = 'Trabalhadores por conta própria',
subtitle = 'Com CNPJ + Sem CNPJ',
caption = foot)+
theme_bw()
> tail(conta_propria, 6) %>%
+ kable()
|date | Conta própria|
|:----------|-------------:|
|2022-11-01 | 25.50|
|2022-12-01 | 25.47|
|2023-01-01 | 25.30|
|2023-02-01 | 25.20|
|2023-03-01 | 25.19|
|2023-04-01 | 25.22|
A quantidade de trabalhadores por conta própria teve um aumento consistente entre 2020 e 2022, e continua andando de mandeira lateral nos últimos meses, porém se mantendo acima de 25 milhões de pessoas. Cravando 25.22 milhões no mês referência.
E por último nessa seção, podemos pegar os dados de trabalhadores com carteira assinada:
## Com carteira assinada
carteira_assinada <-
ocupacao_categoria %>%
mutate('Com carteira' = round(`Empregado no setor privado, exclusive trabalhador doméstico - com carteira de trabalho assinada`/1000, 2)) %>%
mutate('proporcao' = (`Com carteira`/`Empregado`)*100) %>%
select(date,
proporcao,
`Com carteira`)
## tabela
carteira_assinada %>%
select(date,
`Com carteira`) %>%
tail(6) %>%
flextable() %>%
flextable::align(align='c',
part='all') %>%
flextable::width(j = 1:2,
width = 1.8) %>%
flextable::set_header_labels(date = "Período",
'Com carteira' = "Com carteira/CLT (Em milhões)") %>%
flextable::bold(bold = TRUE,
part='header')
## grafico
carteira_assinada %>%
select(date,
`Com carteira`) %>%
ggplot()+
aes(x = date, y= `Com carteira`)+
geom_line(size=0.9,
color='darkblue')+
geom_label_repel(data = filter(carteira_assinada,
date == max(date)),
aes(label = round(`Com carteira`, 2)),
vjust = 0.8,
color = 'white',
fill = 'darkblue',
fontface = 'bold')+
scale_x_date(breaks = '1 year',
labels = date_format('%Y'))+
labs(x = '',
y = 'Em milhões',
title = 'Trabalhadores com carteira assinada',
caption = foot)+
theme_bw()
> carteira_assinada %>%
+ select(date,
+ `Com carteira`) %>%
+ tail(6) %>%
+ kable()
|date | Com carteira|
|:----------|------------:|
|2022-11-01 | 36.79|
|2022-12-01 | 36.86|
|2023-01-01 | 36.81|
|2023-02-01 | 36.81|
|2023-03-01 | 36.69|
|2023-04-01 | 36.81|
Número volta a crescer depois do período de baixa e para mais próximo da máxima histórica, no mês em questão vimos que existem 36.81 milhões de trabalhadores com a carteira assinada.
E agora, podemos partir para a próxima separação de dados, pegando a tabela de número 6390 e 6392 do Sidra, para pegarmos respectivamente o rendimento médio e a massa salarial real do período:
# CPS data: Income
pnad_rendimento =
get_sidra(api='/t/6390/n1/all/v/5933/p/all') %>%
mutate(date = parse_date(`Trimestre Móvel (Código)`,
format='%Y%m')) %>%
select(date, "value" = Valor) %>%
as_tibble()
## CPS data: Income graph
t1 <- ggplot(pnad_rendimento)+
aes(x = date, y= `value`)+
geom_line(size=0.9,
color='darkblue')+
geom_label_repel(data = filter(pnad_rendimento,
date == max(date)),
aes(label = round(`value`, 2)),
vjust = 0.8,
color = 'white',
fill = 'darkblue',
fontface = 'bold')+
scale_x_date(breaks = '1 year',
labels = date_format('%Y'))+
labs(x = '',
y = 'R$',
title = 'Rendimento médio real',
caption = foot)+
theme_bw()
# CPS data: real wage bill
pnad_massa =
get_sidra(api='/t/6392/n1/all/v/6293/p/all') %>%
mutate(date = parse_date(`Trimestre Móvel (Código)`,
format='%Y%m')) %>%
select(date, "value" = Valor) %>%
as_tibble()
## CPS data: real wage bill graph
t2 <- ggplot(pnad_massa)+
aes(x = date, y= `value`/1000)+
geom_line(size=0.9,
color='darkblue')+
geom_label_repel(data = filter(pnad_massa,
date == max(date)),
aes(label = round(`value`/1000, 2)),
vjust = 0.8,
color = 'white',
fill = 'darkblue',
fontface = 'bold')+
scale_x_date(breaks = '1 year',
labels = date_format('%Y'))+
labs(x = '',
y = 'Em milhões (R$)',
title = 'Massa salarial real',
caption = foot)+
theme_bw()
##merge
grid.arrange(t1, t2)
Como podemos ver nessa última parte, o rendimento médio apresenta uma crescente, enquanto a massa salarial tem andado lateralmente nos últimos meses com uma pequena queda nos últimos meses.