Análise Multivariada - Atividade 03
Análise de Agrupamentos (resumo)
O que é?
Grupo de técnicas multivariadas cuja finalidade principal é agregar objetos com base nas características que eles possuem.
Classifica objetos de modo que cada objeto é semelhante aos outros no agrupamento com base em um conjunto de características escolhidas. Os agrupamentos resultantes de objetos devem então exibir:
- Elevada homogeneidade interna (dentro dos agrupamentos);
- Elevada heterogeneidade externa (entre agrupamentos).
- Assim, se a classificação for bem sucedida, teremos graficamente:
- Os objetos dentro de um mesmo agrupamentos estarão próximos;
- Objetos em diferentes agrupamentos estarão distantes.
- Geralmente envolve pelo menos três passos:
- O primeiro é a medida de alguma forma de similaridade ou associação entre as entidades para determinar quantos grupos realmente existem na amostra.
- O segundo passo é o real processo de agrupamento, onde entidades são particionadas em grupos (agrupamentos).
- O último passo é estabelecer o perfil das pessoas ou variáveis para determinar sua composição.
Desenvolvimento conceitual
Os papéis mais comuns que a análise de agrupamentos pode desempenhar em desenvolvimento conceitual incluem os seguintes:
Redução de dados: A análise de agrupamentos pode realizar esse procedimento de redução de dados objetivamente pela redução da informação de uma população inteira ou de uma amostra para a informação sobre subgrupos específicos e menores.
Geração de hipóteses: A análise de agrupamentos também é útil quando um pesquisador deseja desenvolver hipóteses relativas à natureza dos dados ou examinar hipóteses previamente estabelecidas.
Advertências
Em qualquer uso da análise de agrupamentos o pesquisador deve ter especial cuidado para garantir que forte suporte conceitual anteceda a aplicação da técnica.
A análise de agrupamentos é descritiva, não-teórica e não-inferencial;
Não tem base estatística sobre a qual esboçar inferências de uma amostra para uma população;
Muitos clamam que é apenas uma técnica exploratória;
Nada garante soluções únicas, já que a pertinência a um agrupamento para qualquer número de soluções depende de muitos elementos do procedimento. Muitas soluções diferentes podem ser obtidas pela variação de um ou mais elementos;
Se possível, a análise de agrupamentos deve ser aplicada a partir de um modo confirmatório, usando-a para identificar grupos que já têm uma fundamentação conceitual estabelecida quanto à existência dos mesmos.
A análise de agrupamentos sempre criará agrupamentos, independentemente da existência real de alguma estrutura nos dados;
A solução de agrupamentos não é generalizável, pois é totalmente dependente das variáveis usadas como base para a medida de similaridade.
Análise Fatorial versus Análise de Agrupamentos
São semelhantes em seu objetivo de avaliar estrutura inerente aos dados.
- Análise Fatorial
- agrega objetos;
- faz os agrupamentos com base em padrões de variação (correlação) nos dados.
- Análise de Agrupamentos
- está prioritariamente interessada em agregar variáveis;
- faz agregados baseados em distância (proximidade).
Como funciona?
- A análise de agrupamentos executa uma tarefa inata a todos os indivíduos – reconhecimento de padrões e agrupamento.
- O objetivo principal é definir a estrutura dos dados colocando as observações mais parecidas em grupos. Para conseguir isso, devemos tratar de três questões básicas:
- Como medir a similaridade?
- Como formar os agrupamentos?
- Quantos grupos formar?
Análise descritiva
library(pacman)
library(rstatix)
library(e1071)
library(readxl)
library(tidyverse)
library(dplyr)
library(kableExtra)
library(knitr)
library(ggplot2)
library(RColorBrewer)
library(corrplot)
library(ggcorrplot)
library(data.table)
library(cluster)
pacman::p_load(knitr, captioner, bundesligR, stringr)
table_nums <- captioner::captioner(prefix = "Tabela")
tab.1_cap <- table_nums(name = "tab_1",
caption = "Características básicas do dataset credit")
tab.2_cap <- table_nums(name = "tab_2",
caption = "Descrições das variáveis do dataset credit")
tab.3_cap <- table_nums(name = "tab_3",
caption = "Amostra do dataset credit")
tab.4_cap <- table_nums(name = "tab_4",
caption = "Estatísticas resumo das variáveis quantitativas do dataset credit")
tab.5_cap <- table_nums(name = "tab_5",
caption = "Frequências relativas da variável SEXO")
tab.6_cap <- table_nums(name = "tab_6",
caption = "Frequências relativas da variável ESCOLARIDADE")
tab.7_cap <- table_nums(name = "tab_7",
caption = "Frequências relativas da variável ESTADO CIVIL")
tab.8_cap <- table_nums(name = "tab_8",
caption = "Frequências relativas da variável PAG_PADRAO")
tab.9_cap <- table_nums(name = "tab_9",
caption = "Coeficientes de assimetria das variáveis quantitativas")A Análise Descritiva é a fase inicial do processo de estudo dos dados coletados, em que são utilizados métodos de Estatística Descritiva para organizar, resumir, descrever e comparar aspectos importantes de um conjunto de variáveis. A identificação de anomalias e e dados dispersos também faz parte desse tipo de análise.
Sobre o dataset
Foi utilizado o dataset default of credit card clients.xls, retirado do Machine Learning Repository da University of California, Irvine (UCI).
O dataset foi nomeado credit e contém dados pessoais e bancários de consumidores em Taiwan, abrangendo o período de abril a setembro de 2005.
Tendo por base esses dados, o comportamento dos consumidores foi classificado em regular ou irregular, a fim de prever fraudes de crédito.
Após a leitura dos dados, os nomes das variáveis foram modificados para facilitar a compreensão e posterior manipulação dos dados.
#Leitura dos dados
# credit<- read_excel("E:\\Multivariada\\Atividade 03\\default of credit card clients.xls",
# col_types = c("text", "numeric", "numeric","numeric", "numeric",
# "numeric", "numeric", "numeric", "numeric", "numeric",
# "numeric", "numeric", "numeric", "numeric", "numeric",
# "numeric","numeric","numeric","numeric","numeric",
# "numeric","numeric","numeric","numeric","text"))
#Alterando nomes das variáveis
# colnames(credit)<-credit[1,]
# credit<-credit[-1,]
# colnames(credit) <- c("ID",
# "LIMITE",
# "SEXO",
# "ESCOLARIDADE",
# "ESTADO CIVIL",
# "IDADE",
# "HIST_SET2005",
# "HIST_AGO2005",
# "HIST_JUL2005",
# "HIST_JUN2005",
# "HIST_MAI2005",
# "HIST_ABR2005",
# "EXT_SET2005",
# "EXT_AGO2005",
# "EXT_JUL2005",
# "EXT_JUN2005",
# "EXT_MAI2005",
# "EXT_ABR2005",
# "PAG_SET2005",
# "PAG_AGO2005",
# "PAG_JUL2005",
# "PAG_JUN2005",
# "PAG_MAI2005",
# "PAG_ABR2005",
# "PAG_PADRAO")
# library(data.table)
# fwrite(credit, file = "credit_clean.csv")
credit<- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\credit_clean.csv")Características básicas
Tabela 1: Características básicas do dataset credit
caract_basic <- data.frame(NAs = sum(is.na(credit)), Observações = nrow(credit), Variáveis = ncol(credit), Duplicidades = anyDuplicated.data.frame(credit))
knitr::kable(caract_basic)%>% kable_styling(position = "center")| NAs | Observações | Variáveis | Duplicidades |
|---|---|---|---|
| 0 | 30000 | 25 | 0 |
De acordo com a Tabela 1:
- O dataset possui 30.000 observações e 25 variáveis;
- Não possui NAs e nem linhas duplicadas.
Descrição do dataset
Tabela 2: Descrições das variáveis do dataset credit
colunas<- c(colnames(credit)[1:6],"HIST_SET2005 a HIST_ABR2005","EXT_SET2005 a EXT_ABR2005","PAG_SET2005 a PAG_ABR2005","PAG_PADRAO")
descricao <- data.frame(Variável = colunas,
Tipo = c("Texto","Inteiro","Categórica","Categórica","Categórica","Inteiro","Categórica","Inteiro","Inteiro","Binária"),
Descrição = c("Id da observação.",
"Valor do crédito concedido (em Novo dólar taiwanês): inclui tanto o crédito individual ao consumidor quanto o crédito familiar (complementar).",
"Sexo (1= masculino; 2 = feminino).",
"Escolaridade (1 = pós-graduação; 2 = universidade; 3 = ensino médio; 0, 4, 5, 6 = outros).",
"Estado civil (1 = casado; 2 = solteiro; 3 = divorciado; 0 = outros).",
"Idade em anos.",
"Histórico de pagamentos anteriores. Acompanha o registros de pagamentos mensais de abril a setembro de 2005 através da seguinte escala: -2: Sem consumo; -1: pago integralmente; 0: O uso de crédito rotativo; 1 = atraso no pagamento por um mês; 2 = atraso no pagamento por dois meses; ... ; 8 = atraso no pagamento por oito meses; 9 = atraso no pagamento por nove meses ou mais.",
"Valor do extrato da conta (em Novo dólar taiwanês). Acompanha o valor do extrato da conta de abril a setembro de 2005.",
"Valor dos pagamentos anteriores (em Novo dólar taiwanês). Acompanha o valor pago de abril a setembro de 2005",
"Comportamento do cliente quanto aos gastos e pagamentos (0 = irregular; 1 = regular)"))
knitr::kable(descricao)%>% kable_styling(position = "center")| Variável | Tipo | Descrição |
|---|---|---|
| ID | Texto | Id da observação. |
| LIMITE | Inteiro | Valor do crédito concedido (em Novo dólar taiwanês): inclui tanto o crédito individual ao consumidor quanto o crédito familiar (complementar). |
| SEXO | Categórica | Sexo (1= masculino; 2 = feminino). |
| ESCOLARIDADE | Categórica | Escolaridade (1 = pós-graduação; 2 = universidade; 3 = ensino médio; 0, 4, 5, 6 = outros). |
| ESTADO.CIVIL | Categórica | Estado civil (1 = casado; 2 = solteiro; 3 = divorciado; 0 = outros). |
| IDADE | Inteiro | Idade em anos. |
| HIST_SET2005 a HIST_ABR2005 | Categórica | Histórico de pagamentos anteriores. Acompanha o registros de pagamentos mensais de abril a setembro de 2005 através da seguinte escala: -2: Sem consumo; -1: pago integralmente; 0: O uso de crédito rotativo; 1 = atraso no pagamento por um mês; 2 = atraso no pagamento por dois meses; … ; 8 = atraso no pagamento por oito meses; 9 = atraso no pagamento por nove meses ou mais. |
| EXT_SET2005 a EXT_ABR2005 | Inteiro | Valor do extrato da conta (em Novo dólar taiwanês). Acompanha o valor do extrato da conta de abril a setembro de 2005. |
| PAG_SET2005 a PAG_ABR2005 | Inteiro | Valor dos pagamentos anteriores (em Novo dólar taiwanês). Acompanha o valor pago de abril a setembro de 2005 |
| PAG_PADRAO | Binária | Comportamento do cliente quanto aos gastos e pagamentos (0 = irregular; 1 = regular) |
Uma amostra do dataset pode ser visualizada abaixo:
Tabela 3: Amostra do dataset credit
knitr::kable(head(credit))%>% kable_styling(position = "center")| ID | LIMITE | SEXO | ESCOLARIDADE | ESTADO.CIVIL | IDADE | HIST_SET2005 | HIST_AGO2005 | HIST_JUL2005 | HIST_JUN2005 | HIST_MAI2005 | HIST_ABR2005 | EXT_SET2005 | EXT_AGO2005 | EXT_JUL2005 | EXT_JUN2005 | EXT_MAI2005 | EXT_ABR2005 | PAG_SET2005 | PAG_AGO2005 | PAG_JUL2005 | PAG_JUN2005 | PAG_MAI2005 | PAG_ABR2005 | PAG_PADRAO |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 20000 | 2 | 2 | 1 | 24 | 2 | 2 | -1 | -1 | -2 | -2 | 3913 | 3102 | 689 | 0 | 0 | 0 | 0 | 689 | 0 | 0 | 0 | 0 | 1 |
| 2 | 120000 | 2 | 2 | 2 | 26 | -1 | 2 | 0 | 0 | 0 | 2 | 2682 | 1725 | 2682 | 3272 | 3455 | 3261 | 0 | 1000 | 1000 | 1000 | 0 | 2000 | 1 |
| 3 | 90000 | 2 | 2 | 2 | 34 | 0 | 0 | 0 | 0 | 0 | 0 | 29239 | 14027 | 13559 | 14331 | 14948 | 15549 | 1518 | 1500 | 1000 | 1000 | 1000 | 5000 | 0 |
| 4 | 50000 | 2 | 2 | 1 | 37 | 0 | 0 | 0 | 0 | 0 | 0 | 46990 | 48233 | 49291 | 28314 | 28959 | 29547 | 2000 | 2019 | 1200 | 1100 | 1069 | 1000 | 0 |
| 5 | 50000 | 1 | 2 | 1 | 57 | -1 | 0 | -1 | 0 | 0 | 0 | 8617 | 5670 | 35835 | 20940 | 19146 | 19131 | 2000 | 36681 | 10000 | 9000 | 689 | 679 | 0 |
| 6 | 50000 | 1 | 1 | 2 | 37 | 0 | 0 | 0 | 0 | 0 | 0 | 64400 | 57069 | 57608 | 19394 | 19619 | 20024 | 2500 | 1815 | 657 | 1000 | 1000 | 800 | 0 |
Estatísticas resumo (variáveis quantitativas)
O cálculo das estatísticas resumo foi feito para as variáveis quantitativas.
Tabela 4: Estatísticas resumo das variáveis quantitativas do dataset credit
knitr::kable(get_summary_stats(credit[,c(2,6,13:24)]) [,-c(2,8,9,12,13)])%>% kable_styling(position = "center")| variable | min | max | median | q1 | q3 | mean | sd |
|---|---|---|---|---|---|---|---|
| EXT_ABR2005 | -339603 | 961664 | 17071.0 | 1256.00 | 49198.25 | 38871.760 | 59554.108 |
| EXT_AGO2005 | -69777 | 983931 | 21200.0 | 2984.75 | 64006.25 | 49179.075 | 71173.769 |
| EXT_JUL2005 | -157264 | 1664089 | 20088.5 | 2666.25 | 60164.75 | 47013.155 | 69349.387 |
| EXT_JUN2005 | -170000 | 891586 | 19052.0 | 2326.75 | 54506.00 | 43262.949 | 64332.856 |
| EXT_MAI2005 | -81334 | 927171 | 18104.5 | 1763.00 | 50190.50 | 40311.401 | 60797.156 |
| EXT_SET2005 | -165580 | 964511 | 22381.5 | 3558.75 | 67091.00 | 51223.331 | 73635.861 |
| IDADE | 21 | 79 | 34.0 | 28.00 | 41.00 | 35.486 | 9.218 |
| LIMITE | 10000 | 1000000 | 140000.0 | 50000.00 | 240000.00 | 167484.323 | 129747.662 |
| PAG_ABR2005 | 0 | 528666 | 1500.0 | 117.75 | 4000.00 | 5215.503 | 17777.466 |
| PAG_AGO2005 | 0 | 1684259 | 2009.0 | 833.00 | 5000.00 | 5921.164 | 23040.870 |
| PAG_JUL2005 | 0 | 896040 | 1800.0 | 390.00 | 4505.00 | 5225.682 | 17606.961 |
| PAG_JUN2005 | 0 | 621000 | 1500.0 | 296.00 | 4013.25 | 4826.077 | 15666.160 |
| PAG_MAI2005 | 0 | 426529 | 1500.0 | 252.50 | 4031.50 | 4799.388 | 15278.306 |
| PAG_SET2005 | 0 | 873552 | 2100.0 | 1000.00 | 5006.00 | 5663.580 | 16563.280 |
Para a variável IDADE, temos que as idades mínima e máxima observadas são 21 e 79 anos, respectivamente. A mediana é 39 anos, ou seja, 50% dos clientes observados possuem idade menor ou igual a 39 anos.
Para a variável LIMITE, temos que o valor mínimo e máximo de crédito concedido são NT$10.000 e NT$1.000.000 , respectivamente. A mediana é NT$140.000, ou seja, 50% dos clientes observados foram concedidos um valor em crédito menor ou igual a NT$140.000.
As medianas das variáveis PAG_SET2005 a PAG_ABR2005 assumem valores na faixa NT$1500-NT$2100, ou seja, 50% dos clientes observados fizeram um pagamento entre NT$1500 e NT$2100.
As medianas das variáveis EXT_SET2005 a EXT_ABR2005 assumem valores na faixa NT$17071-NT$22381.5, ou seja, 50% dos extratos de clientes observados possuem valor entre NT$17071 e NT$22381.5.
Observem que, pelo comportamento mediano, podemos perceber que muitos dos clientes possuem um valor de extrato superior ao valor de pagamento.
Tabelas de frequências relativas
Foram feitas tabelas de frequências relativas para as variáveis categóricas relativas a características pessoais (SEXO, ESCOLARIDADE e ESTADO CIVIL) e para a variável binária (PAG_PADRAO).
Tabela 5: Frequências relativas da variável SEXO
sexo <- data.frame(round((table(credit$SEXO)/nrow(credit))*100,2))
colnames(sexo) <- c("SEXO","Frequência relativa (%)")
knitr::kable(sexo)%>% kable_styling(position = "center")| SEXO | Frequência relativa (%) |
|---|---|
| 1 | 39.63 |
| 2 | 60.37 |
- 39.63% dos clientes são do sexo masculino
- 60.37% dos clientes são do sexo feminino
Tabela 6: Frequências relativas da variável ESCOLARIDADE
escolaridade <- data.frame(round((table(credit$ESCOLARIDADE)/nrow(credit))*100,2))
colnames(escolaridade) <- c("ESCOLARIDADE","Frequência relativa (%)")
knitr::kable(escolaridade)%>% kable_styling(position = "center")| ESCOLARIDADE | Frequência relativa (%) |
|---|---|
| 0 | 0.05 |
| 1 | 35.28 |
| 2 | 46.77 |
| 3 | 16.39 |
| 4 | 0.41 |
| 5 | 0.93 |
| 6 | 0.17 |
- 46.77% dos clientes possuem graduação
- 35.28% dos clientes possuem pós-graduação
- 16.39% dos clientes possuem somente ensino médio
- 1.56% dos clientes estão em outras faixas de escolaridade
Tabela 7: Frequências relativas da variável ESTADO CIVIL
# est_civil <- data.frame(round((table(credit$`ESTADO CIVIL`)/nrow(credit))*100,2))
# colnames(est_civil) <- c("ESTADO CIVIL","Frequência relativa (%)")
# knitr::kable(est_civil)%>% kable_styling(position = "center")
est_civil <- data.frame(round((table(credit$ESTADO.CIVIL)/nrow(credit))*100,2))
colnames(est_civil) <- c("ESTADO CIVIL","Frequência relativa (%)")
knitr::kable(est_civil)%>% kable_styling(position = "center")| ESTADO CIVIL | Frequência relativa (%) |
|---|---|
| 0 | 0.18 |
| 1 | 45.53 |
| 2 | 53.21 |
| 3 | 1.08 |
- 53.21% dos clientes são solteiros
- 45.53 % dos clientes são casados
- 1.08% dos clientes são divorciados
- 0.18% dos clientes possuem outro estado civil
Tabela 8: Frequências relativas da variável PAG_PADRAO
pag_padr <-data.frame(round((table(credit$PAG_PADRAO)/nrow(credit))*100,2))
colnames(pag_padr) <- c("PAG_PADRAO","Frequência relativa (%)")
knitr::kable(pag_padr)%>% kable_styling(position = "center")| PAG_PADRAO | Frequência relativa (%) |
|---|---|
| 0 | 77.88 |
| 1 | 22.12 |
- Foi detectado comportamento irregular em 77.88% dos clientes observados
- Foi detectado comportamento regular em 22.12% dos clientes observados
Gráficos de barras (variáveis de histórico de pagamento)
par(mfrow=c(3,2))
histset2005<- data.frame(table(credit$HIST_SET2005))
colnames(histset2005)<- c("HIST_SET2005","Frequência")
histago2005<- data.frame(table(credit$HIST_AGO2005))
colnames(histago2005)<- c("HIST_AGO2005","Frequência")
histjul2005<- data.frame(table(credit$HIST_JUL2005))
colnames(histjul2005)<- c("HIST_JUL2005","Frequência")
histjun2005<- data.frame(table(credit$HIST_JUN2005))
colnames(histjun2005)<- c("HIST_JUN2005","Frequência")
histmai2005<- data.frame(table(credit$HIST_MAI2005))
colnames(histmai2005)<- c("HIST_MAI2005","Frequência")
histabr2005<- data.frame(table(credit$HIST_ABR2005))
colnames(histabr2005)<- c("HIST_ABR2005","Frequência")
ggplot(data=histset2005, aes(x=HIST_SET2005, y=Frequência)) +
geom_bar(stat="identity", color="blue", fill="white")+
geom_text(aes(label=Frequência), vjust=-0.3, color="black", size=3.5)+
labs(x="\nHIST_SET2005",y="Frequência\n", title="Frequências absolutas - HIST_SET2005\n")+
theme_bw()ggplot(data=histago2005, aes(x=HIST_AGO2005, y=Frequência)) +
geom_bar(stat="identity", color="blue", fill="white")+
geom_text(aes(label=Frequência), vjust=-0.3, color="black", size=3.5)+
labs(x="\nHIST_AGO2005",y="Frequência\n", title="Frequências absolutas - HIST_AGO2005\n")+
theme_bw()ggplot(data=histjul2005, aes(x=HIST_JUL2005, y=Frequência)) +
geom_bar(stat="identity", color="blue", fill="white")+
geom_text(aes(label=Frequência), vjust=-0.3, color="black", size=3.5)+
labs(x="\nHIST_JUL2005",y="Frequência\n", title="Frequências absolutas - HIST_JUL2005\n")+
theme_bw()ggplot(data=histjun2005, aes(x=HIST_JUN2005, y=Frequência)) +
geom_bar(stat="identity", color="blue", fill="white")+
geom_text(aes(label=Frequência), vjust=-0.3, color="black", size=3.5)+
labs(x="\nHIST_JUN2005",y="Frequência\n", title="Frequências absolutas - HIST_JUN2005\n")+
theme_bw()ggplot(data=histmai2005, aes(x=HIST_MAI2005, y=Frequência)) +
geom_bar(stat="identity", color="blue", fill="white")+
geom_text(aes(label=Frequência), vjust=-0.3, color="black", size=3.5)+
labs(x="\nHIST_MAI2005",y="Frequência\n", title="Frequências absolutas - HIST_MAI2005\n")+
theme_bw()ggplot(data=histabr2005, aes(x=HIST_ABR2005, y=Frequência)) +
geom_bar(stat="identity", color="blue", fill="white")+
geom_text(aes(label=Frequência), vjust=-0.3, color="black", size=3.5)+
labs(x="\nHIST_ABR2005",y="Frequência\n", title="Frequências absolutas - HIST_ABR2005\n")+
theme_bw()
- Podemos observar que, para os meses entre abril e setembro de 2005, o
histórico de pagamentos apresenta em maior frequência o uso de credito
rotativo (0).
Coeficientes de assimetria
A Tabela 9 contém os coeficientes de assimetria para as variáveis quantitativas do dataset.
A assimetria negativa indica que a média dos dados é menor que a mediana e, portanto, que a distribuição dos dados é assimétrica à esquerda. Já a assimetria positiva indica que a média dos dados é maior que a mediana e, portanto, que a distribuição dos dados é assimétrica à direita.
Tabela 9: Coeficientes de assimetria das variáveis quantitativas
knitr::kable(apply(credit[,c(2,6,13:24)],2, function(x) round(skewness(x),2)),col.names = "Coeficiente de assimetria")%>% kable_styling(position = "center")| Coeficiente de assimetria | |
|---|---|
| LIMITE | 0.99 |
| IDADE | 0.73 |
| EXT_SET2005 | 2.66 |
| EXT_AGO2005 | 2.70 |
| EXT_JUL2005 | 3.09 |
| EXT_JUN2005 | 2.82 |
| EXT_MAI2005 | 2.88 |
| EXT_ABR2005 | 2.85 |
| PAG_SET2005 | 14.67 |
| PAG_AGO2005 | 30.45 |
| PAG_JUL2005 | 17.21 |
| PAG_JUN2005 | 12.90 |
| PAG_MAI2005 | 11.13 |
| PAG_ABR2005 | 10.64 |
De acordo com a Tabela 9, temos que todas as variáveis quantitativas são assimétricas à direita.
Correlograma
O correlograma abaixo mostra os coeficientes de correlação de Pearson para todas as variáveis quantitativas do dataset.
corr <- cor(credit[,c(2,6,13:24)]) #Matriz de correlação
ggcorrplot(corr,outline.color = "white",type = "lower",lab = TRUE,digits = 2, lab_size = 3)- Temos que as maiores correlações ocorreram entre os valores dos extratos de abril a setembro de 2005, como destacado pela área em vermelho.
Análise de Agrupamento (Clustering)
tab.10_cap <- table_nums(name = "tab_10",
caption = "Intervalos de classificação da silhueta média (Kaufman e Rousseeuw, 1989)")
tab.11_cap <- table_nums(name = "tab_11",
caption = "Experimento 1 - Medoids da solução com k=3")
tab.12_cap <- table_nums(name = "tab_12",
caption = "Experimento 1 - Matriz de confusão para a solução com k=2")
tab.13_cap <- table_nums(name = "tab_13",
caption = "Experimento 2 - Medoids da solução com k=4")
tab.14_cap <- table_nums(name = "tab_13",
caption = "Experimento 2 - Matriz de confusão para a solução com k=2")
tab.15_cap <- table_nums(name = "tab_15",
caption = " Experimento 3 - Medoids da solução com k=2")
tab.16_cap <- table_nums(name = "tab_16",
caption = "Experimento 3 - Matriz de confusão para a solução com k=2")
tab.17_cap <- table_nums(name = "tab_17",
caption = " Experimento 4 - Medoids da solução com k=3")
tab.18_cap <- table_nums(name = "tab_18",
caption = " Experimento 4 - Percentual de acerto para a solução com k=2")Depois da análise descritiva, demos início ao agrupamento, ou clustering, dos dados.
Três questões básicas devem ser abordadas em um problema de agrupamento (Hair e Babin, 2018):
(1) Como medir a similaridade?
o primeiro passo da tarefa de agrupamento consiste na escolha de como a similaridade/dissimilaridade entre as observações será medida. A dissimilaridade nada mais é que a distância entre as observações.
(2) Como formar os agrupamentos?
O segundo passo consiste na escolha do algoritmo de agrupamento, que dará origem aos grupos de acordo com as dissimilaridades obtidas no passo 1.
(3) Quantos grupos formar?
Uma vez obtido um agrupamento (solução), é de suma importância avaliá- lo e verificar se, de fato, representa bem a estrutura dos dados. Esse tipo de avaliação pode ser feita mediante a aplicação de índices de validação. Logo, o terceiro e último passo consiste em e avaliar e comparar as soluções produzidas no segundo. Nesse trabalho usaremos o índice de silhueta, mais especificamente, a silhueta média como um indicador de qualidade do agrupamento.
Tabela 10: Intervalos de classificação da silhueta média (Kaufman e Rousseeuw, 1989)
sil_tabela <- data.frame(a=c("0.71-1","0.51 − 0.70","0.26 − 0.50","≤ 0.25"),
d=c("Estrutura forte encontrada nos dados",
"Estrutura razoável encontrada nos dados",
"Estrutura fraca, possivelmente artificial; Avaliar a aplicação de outros algoritmos nos dados",
"Não foi encontrada estrutura substancial nos dados"))
colnames(sil_tabela) <- c("Valor da silhueta média","Descrição")
knitr::kable(sil_tabela)%>% kable_styling(position = "center")| Valor da silhueta média | Descrição |
|---|---|
| 0.71-1 | Estrutura forte encontrada nos dados |
| 0.51 − 0.70 | Estrutura razoável encontrada nos dados |
| 0.26 − 0.50 | Estrutura fraca, possivelmente artificial; Avaliar a aplicação de outros algoritmos nos dados |
| ≤ 0.25 | Não foi encontrada estrutura substancial nos dados |
Distância de Gower + PAM
As distâncias Euclidiana e Manhattan são comumente utilizadas, porém, ambas são aplicáveis somente para dados numéricos e, como já vimos, o dataset credit possui variáveis categóricas e numéricas.
Levando em consideração essa particularidade do dataset, primeiramente utilizamos a distância de Gower, uma métrica que pode ser usada para calcular a distância entre duas observações cujos atributos/variáveis são um misto de valores categóricos e quantitativos.
A distância de Gower foi empregada através da função daisy do pacote cluster. Com a matriz de distâncias obtida, o algoritmo de agrupamento PAM foi aplicado variando o número de grupos k entre 2 e 5. A qualidade dos agrupamentos foi verificada através da silhueta média das soluções.
Foram realizados dois experimentos diferentes considerando a combinação da distância de Gower e do algoritmo PAM:
- EXPERIMENTO 1: A distância foi calculada para todas as variáveis do dataset, com exceção de ID e PAG_PADRAO;
- EXPERIMENTO 2: A distância foi calculada usando todas as variáveis numéricas e as variáveis categóricas HIST_SET2005 a HIST_ABR2005, mantendo a exclusão das variáveis ID e PAG_PADRAO.
O resultado do EXPERIMENTO 1 pode ser visualizado no gráfico abaixo:
# credit$HIST_SET2005<- as.factor(credit$HIST_SET2005)
# credit$HIST_AGO2005<- as.factor(credit$HIST_AGO2005)
# credit$HIST_JUL2005<- as.factor(credit$HIST_JUL2005)
# credit$HIST_JUN2005<- as.factor(credit$HIST_JUN2005)
# credit$HIST_MAI2005<- as.factor(credit$HIST_MAI2005)
# credit$HIST_ABR2005<- as.factor(credit$HIST_ABR2005)
# credit$SEXO<-as.factor(credit$SEXO)
# credit$ESCOLARIDADE<-as.factor(credit$ESCOLARIDADE)
# credit$ESTADO.CIVIL<-as.factor(credit$ESTADO.CIVIL)
#-------------------- Com todas as variáveis -----------------------------------
# gower_df <- daisy(credit[,-c(1,25)],
# metric = "gower" )
# saveRDS(gower_df, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\credit_gowerdf_complete.rds")
# rm(list = ls())
# gc()
# .rs.restartR()
#
# library(cluster)
# library(data.table)
#
# gower_df<-readRDS("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\credit_gowerdf_complete.rds", refhook = NULL)
#
# i=2
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_gower_complete.Rdata")
# dois_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(dois_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_gower_complete.csv")
# rm(list=c("pam_clusters","dois_grupos"))
# gc()
# i=3
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_complete.Rdata")
# tres_grupos <-data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(tres_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_complete.csv")
# rm(list=c("pam_clusters","tres_grupos"))
# gc()
# i=4
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_complete.Rdata")
# quatro_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(quatro_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_complete.csv")
#
# rm(list=c("pam_clusters","quatro_grupos"))
# gc()
# i=5
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_gower_complete.Rdata")
# cinco_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(cinco_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_gower_complete.csv")
# rm(list = ls())
# gc()
# .rs.restartR()
#--------------------- Sem sexo, escolaridade e estado civil -------------------------
# library(cluster)
# library(data.table)
# credit<- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\credit_clean.csv")
# credit$HIST_SET2005<- as.factor(credit$HIST_SET2005)
# credit$HIST_AGO2005<- as.factor(credit$HIST_AGO2005)
# credit$HIST_JUL2005<- as.factor(credit$HIST_JUL2005)
# credit$HIST_JUN2005<- as.factor(credit$HIST_JUN2005)
# credit$HIST_MAI2005<- as.factor(credit$HIST_MAI2005)
# credit$HIST_ABR2005<- as.factor(credit$HIST_ABR2005)
# gower_df <- daisy(credit[,-c(1,3:5,25)],
# metric = "gower" )
# saveRDS(gower_df, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\credit_gowerdf_notcomplete.rds")
# rm(list = ls())
# gc()
# .rs.restartR()
# library(cluster)
# library(data.table)
# gower_df<-readRDS("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\credit_gowerdf_notcomplete.rds", refhook = NULL)
# i=2
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_gower_notcomplete.Rdata")
# dois_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(dois_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_gower_notcomplete.csv")
# rm(list=c("pam_clusters","dois_grupos"))
# gc()
# i=3
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_notcomplete.Rdata")
# tres_grupos <-data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(tres_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_notcomplete.csv")
# rm(list=c("pam_clusters","tres_grupos"))
# gc()
# i=4
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_notcomplete.Rdata")
# quatro_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(quatro_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_notcomplete.csv")
# rm(list=c("pam_clusters","quatro_grupos"))
# gc()
# i=5
# pam_clusters <- pam(gower_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_gower_notcomplete.Rdata")
# cinco_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(cinco_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_gower_notcomplete.csv")
# rm(list = ls())
# gc()
# .rs.restartR()
dois_grupos<- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_gower_complete.csv")
tres_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_complete.csv")
quatro_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_complete.csv")
cinco_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_gower_complete.csv")
silhueta <- cbind.data.frame (grupos=as.factor(1:5),silhueta=c(0, dois_grupos[1,],tres_grupos[1,],quatro_grupos[1,],cinco_grupos[1,]))
ggplot(data=silhueta, aes(x=grupos, y=silhueta, group=1, label=as.character(round(silhueta,2)))) +
geom_line()+
geom_point()+
geom_text(hjust=0, vjust=-1.5)+
labs(x="\nGrupos",y="Valor da silhueta média\n", title="Experimento 1 - Valor da silhueta média de acordo com o número de grupos k\n")+
scale_y_continuous(breaks = seq(0,0.6,by=0.1), limits= c(0,0.6))+
theme_classic()De acordo com os valores da silhueta média, no Experimento 1 a melhor solução utilizando a distância de Gower em conjunto ao algoritmo PAM é para \(k=3\) grupos.
Com a solução do PAM para \(k=3\) grupos, tentamos interpretar o comportamento de cada cluster com a ajuda dos medoids da solução.
Tabela 11: Experimento 1 - Medoids da solução com k=3
load("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_complete.Rdata")
knitr::kable(credit[pam_clusters$medoids, ])%>% kable_styling(position = "center")| ID | LIMITE | SEXO | ESCOLARIDADE | ESTADO.CIVIL | IDADE | HIST_SET2005 | HIST_AGO2005 | HIST_JUL2005 | HIST_JUN2005 | HIST_MAI2005 | HIST_ABR2005 | EXT_SET2005 | EXT_AGO2005 | EXT_JUL2005 | EXT_JUN2005 | EXT_MAI2005 | EXT_ABR2005 | PAG_SET2005 | PAG_AGO2005 | PAG_JUL2005 | PAG_JUN2005 | PAG_MAI2005 | PAG_ABR2005 | PAG_PADRAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3893 | 3893 | 170000 | 2 | 1 | 1 | 36 | -1 | -1 | -1 | -1 | -1 | -1 | 1218 | 2434 | 1537 | 2156 | 1898 | 2656 | 2434 | 1537 | 2156 | 1898 | 2656 | 1626 | 0 |
| 26299 | 26299 | 80000 | 2 | 2 | 2 | 34 | 0 | 0 | 0 | 0 | 0 | 0 | 64553 | 52484 | 41048 | 31786 | 29105 | 28294 | 1784 | 1874 | 2000 | 1011 | 1100 | 1154 | 0 |
| 17641 | 17641 | 200000 | 2 | 1 | 2 | 34 | -2 | -2 | -2 | -2 | -2 | -2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Na tabela acima, cada linha contém a observação de credit escolhida como medoid na solução ótima (\(k=3\)).
A partir desta tabela, podemos inferir que os clientes pertencentes ao Cluster 1 (linha 1) têm as seguintes características representativas (de acordo com o medoid): o limite do crédito concedido é de NT$170k, são do sexo feminino, com pós graduação completa, casadas, idade média de 36 anos, com o histórico de pagamentos de abril a setembro de 2015 pago integralmente, com o valor do extrato da conta desse mesmo período variando entre 1218 a 2656 Novo dólar taiwanês, o valor dos pagamentos do período abordado entre NT$1626 e NT$2656, e possuem comportamento irregular de gastos e pagamentos.
Observe que nem todos os clientes serão exatamente assim; os medoides são apenas uma representantes do cluster abordado.
Interpretações similares podem ser feitas para os outros clusters. Podemos notar que o segundo cluster aparenta ser de pessoas em que o extrato é bem maior que os pagamentos dos mesmos meses, com limite de NT$80k, com ensino médio inferior aos outros clusters (universidade), usando crédito rotativo e com comportamento irregular. Enquanto o terceiro, possui um comportamento regular, um limite médio de NT$200k e não apresentam consumos nos meses estudados, nem extratos e nem pagamentos.
Para a solução com \(k=2\) grupos, comparamos o agrupamento obtido no Experimento 1 com a coluna PAG_PADRAO presente no dataset credit, obtendo os seguintes resultados:
Tabela 12: Experimento 1 - Matriz de confusão para a solução com k=2
aux <- dois_grupos
aux<- as.character(aux[-1,])
#table(aux)
# 2 aparece em maior quantidade, logo, corresponde ao grupo 0 da base original
aux [which(aux=="2")] <- "0"
# correspondencia <- data.frame(PAG_PADRAO = sum(as.character(credit$PAG_PADRAO) == aux)/30000)
#
# correspondencia <- round(correspondencia*100,2)
# colnames(correspondencia) <- c(" Exp1 - Acertos (%)")
# knitr::kable(correspondencia)%>% kable_styling(position = "center")
#Import required library
library(caret)
#Creates vectors having data points
expected_value <- factor(aux)
predicted_value <- factor(credit$PAG_PADRAO)
#Creating confusion matrix
example <- confusionMatrix(data=predicted_value, reference = expected_value)
#Display results
knitr::kable(example$table)%>% kable_styling(position = "center")| 0 | 1 | |
|---|---|---|
| 0 | 15636 | 7728 |
| 1 | 4631 | 2005 |
- Na solução de agrupamento obtida, os objetos foram alocados aos clusters 1 e 2. Por possuir mais observações, tal qual o grupo 0 da base original, transformou-se o “2” em “0”.
- Ao compararmos a variável PAG_PADRAO com a solução do agrupamento para \(k=2\) do Experimento 1, temos que a acurácia foi 58.8%.
- De acordo com a tabela, o agrupamento obtido alocou um objeto pertencente ao grupo 0 originalmente ao grupo 0 do agrupamento em 15636 casos e alocou um objeto do grupo 0 ao grupo 1 em 4631 casos.
- O agrupamento obtido alocou um objeto pertencente ao grupo 1 originalmente ao grupo 0 do agrupamento em 7728 casos, e alocou um objeto do grupo 1 ao grupo 1 do agrupamento em 2005 casos.
Quanto ao EXPERIMENTO 2, seus resultados podem ser visualizados no gráfico abaixo:
dois_grupos<- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_gower_notcomplete.csv")
tres_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_gower_notcomplete.csv")
quatro_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_notcomplete.csv")
cinco_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_gower_notcomplete.csv")
silhueta <- cbind.data.frame (grupos=as.factor(1:5),silhueta=c(0, dois_grupos[1,],tres_grupos[1,],quatro_grupos[1,],cinco_grupos[1,]))
ggplot(data=silhueta, aes(x=grupos, y=silhueta, group=1, label=as.character(round(silhueta,2)))) +
geom_line()+
geom_point()+
geom_text(hjust=0, vjust=-1.5)+
labs(x="\nGrupos",y="Valor da silhueta média\n", title="Experimento 2 - Valor da silhueta média de acordo com o número de grupos k\n")+
scale_y_continuous(breaks = seq(0,0.6,by=0.1), limits= c(0,0.6))+
theme_classic()De acordo com os valores da silhueta média, no Experimento 2 a melhor solução utilizando a distância de Gower em conjunto ao algoritmo PAM é para \(k=4\) grupos.
Com a solução do PAM para \(k=4\) grupos, tentamos interpretar o comportamento de cada cluster com a ajuda dos medoids da solução.
Tabela 13: Experimento 2 - Medoids da solução com k=4
load("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_gower_notcomplete.Rdata")
knitr::kable(credit[pam_clusters$medoids, ])%>% kable_styling(position = "center")| ID | LIMITE | SEXO | ESCOLARIDADE | ESTADO.CIVIL | IDADE | HIST_SET2005 | HIST_AGO2005 | HIST_JUL2005 | HIST_JUN2005 | HIST_MAI2005 | HIST_ABR2005 | EXT_SET2005 | EXT_AGO2005 | EXT_JUL2005 | EXT_JUN2005 | EXT_MAI2005 | EXT_ABR2005 | PAG_SET2005 | PAG_AGO2005 | PAG_JUL2005 | PAG_JUN2005 | PAG_MAI2005 | PAG_ABR2005 | PAG_PADRAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 15930 | 15930 | 60000 | 2 | 2 | 1 | 32 | 2 | 2 | 2 | 2 | 2 | 2 | 20524 | 21584 | 22437 | 22771 | 23099 | 23583 | 1700 | 1500 | 1000 | 1000 | 1000 | 0 | 1 |
| 29556 | 29556 | 100000 | 1 | 1 | 1 | 33 | 0 | 0 | 0 | 0 | 0 | 0 | 49415 | 50851 | 49528 | 50604 | 40966 | 40308 | 2284 | 1961 | 2037 | 1434 | 1469 | 1483 | 0 |
| 14857 | 14857 | 210000 | 2 | 2 | 1 | 35 | -1 | -1 | -1 | -1 | -1 | -1 | 1338 | 1508 | 1409 | 1549 | 2454 | 946 | 1508 | 1409 | 1549 | 2454 | 946 | 1525 | 0 |
| 13471 | 13471 | 200000 | 1 | 1 | 1 | 36 | -2 | -2 | -2 | -2 | -2 | -2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
As características dos clientes do grupo/cluster 1 são: limite do crédito concedido de NT$60k, sexo feminino, escolaridade graduação completa, casados, idade média de 32 anos, atraso médio de 2 meses em todos os pagamentos dos meses abordados, extratos entre NT$20k e NT$24k, pagamentos entre NT$1k e NT$1.7k com exceção de abril, que apresenta valor 0 e comportamento regular.
No segundo grupo/cluster, as principais características são: limite de 100k, sexo masculino, casados, com idade média de 33 anos, pós graduação completa, usando crédito rotativo em todos os meses abordados, extratos variando de NT$40k a NT$51k, pagamentos entre NT$1.4k e NT$2.3k e comportamento irregular.
O terceiro cluster têm como características: valor limite do crédito concedido de NT$210k, mulheres casadas, graduação completa, com 35 anos, pagamentos pagos integralmente,com extratos e pagamentos entre NT$956 e NT$2454 e comportamento irregular.
O quarto cluster possui características similares ao terceiro cluster do experimento 1, com exceção do perfil demográfico: o sexo é masculino, estado civil casado e idade 36 anos.
Novamente foi feita a comparação entre a solução com \(k=2\) grupos e a coluna PAG_PADRAO presente no dataset credit, obtendo a seguinte matriz de confusão:
Tabela 18:
aux <- dois_grupos
aux<- as.character(aux[-1,])
# table(aux)
# 2 aparece em maior quantidade, logo, corresponde ao grupo 0 da base original
aux [which(aux=="2")] <- "0"
# correspondencia <- data.frame(PAG_PADRAO = sum(as.character(credit$PAG_PADRAO) == aux)/30000)
#
# correspondencia <- round(correspondencia*100,2)
# colnames(correspondencia) <- c(" Exp1 - Acertos (%)")
# knitr::kable(correspondencia)%>% kable_styling(position = "center")
#Creates vectors having data points
expected_value <- factor(aux)
predicted_value <- factor(credit$PAG_PADRAO)
#Creating confusion matrix
example <- confusionMatrix(data=predicted_value, reference = expected_value)
#Display results
knitr::kable(example$table)%>% kable_styling(position = "center")| 0 | 1 | |
|---|---|---|
| 0 | 14998 | 8366 |
| 1 | 4517 | 2119 |
- Na solução de agrupamento obtida, os objetos foram alocados aos clusters 1 e 2. Por possuir mais observações, tal qual o grupo 0 da base original, transformou-se o “2” em “0”.
- Ao compararmos a variável PAG_PADRAO com a solução do agrupamento para \(k=2\) do Experimento 2, temos que a acurácia foi de 57.06%.
- De acordo com a tabela, o agrupamento obtido alocou um objeto pertencente ao grupo 0 originalmente ao grupo 0 do agrupamento em 14998 casos e alocou um objeto do grupo 0 ao grupo 1 em 4517 casos.
- O agrupamento obtido alocou um objeto pertencente ao grupo 1 originalmente ao grupo 0 do agrupamento em 8366 casos, e alocou um objeto do grupo 1 ao grupo 1 do agrupamento em 2119 casos.
Distância Euclidiana + PAM
Como os resultados obtidos utilizando a distância de Gower em conjunto ao algoritmo PAM não foram satisfatórios, isto é, a análise de qualidade segundo a silhueta média não indicou o número “correto” de grupos, optamos por realizar um terceiro experimento, dessa vez usando a distância Euclidiana.
Comentamos anteriormente que a distância euclidiana deve ser usada somente com variáveis quantitativas, portanto, utilizamos neste experimento somente as variáveis quantitativas do dataset:
- LIMITE
- IDADE
- EXT_SET2005
- EXT_AGO2005
- EXT_JUL2005
- EXT_JUN2005
- EXT_MAI2005
- EXT_ABR2005
- PAG_SET2005
- PAG_AGO2005
- PAG_JUL2005
- PAG_JUN2005
- PAG_MAI2005
- PAG_ABR2005
Previamente ao cálculo das distâncias, essas variáveis foram padronizadas com o auxílio da função scale.
A matriz de distância foi obtida pela função distances do pacote distances.
Com a matriz de distâncias euclidiana em mãos, o Experimento 3 consistiu em aplicar o algoritmo de agrupamento PAM variando o número de grupos k entre 2 e 5. A qualidade dos agrupamentos foi verificada através da silhueta média das soluções.
# library(distances)
# credit_padronizado <- credit[,c(2,6,13:24)]
# credit_padronizado<- data.frame(apply(credit_padronizado,2,scale))
# euclidean_df <- distances(credit_padronizado)
#
#
# i=2
# pam_clusters <- pam(euclidean_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_euclidean.Rdata")
# dois_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(dois_grupos, file = "C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\doisgrupos_euclidean.csv")
# i=3
# pam_clusters <- pam(euclidean_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\tresgrupos_euclidean.Rdata")
# tres_grupos <-data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(tres_grupos, file = "C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\tresgrupos_euclidean.csv")
#
# i=4
# pam_clusters <- pam(euclidean_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\quatrogrupos_euclidean.Rdata")
# quatro_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(quatro_grupos, file = "C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\quatrogrupos_euclidean.csv")
# i=5
# pam_clusters <- pam(euclidean_df,diss = TRUE, k = i)
# save(pam_clusters,file="C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\cincogrupos_euclidean.Rdata")
# cinco_grupos <- data.frame(c(as.vector(pam_clusters$silinfo$avg.width),as.vector(pam_clusters$clustering)))
# fwrite(cinco_grupos, file = "C:\\Users\\Josh\\Desktop\\VICTÓRIA VARGAS\\cincogrupos_euclidean.csv")
dois_grupos<- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_euclidean.csv")
tres_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_euclidean.csv")
quatro_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_euclidean.csv")
cinco_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_euclidean.csv")
silhueta <- cbind.data.frame (grupos=as.factor(1:5),silhueta=c(0, dois_grupos[1,],tres_grupos[1,],quatro_grupos[1,],cinco_grupos[1,]))
ggplot(data=silhueta, aes(x=grupos, y=silhueta, group=1, label=as.character(round(silhueta,2)))) +
geom_line()+
geom_point()+
geom_text(hjust=0, vjust=-1.5)+
labs(x="\nGrupos",y="Valor da silhueta média\n", title="Experimento 3 - Valor da silhueta média de acordo com o número de grupos k\n")+
scale_y_continuous(breaks = seq(0,0.6,by=0.1), limits= c(0,0.6))+
theme_classic()Note que, de acordo com os valores da silhueta média, a melhor solução utilizando a distância de Euclidiana em conjunto ao algoritmo PAM é para \(k=2\) grupos, o número “correto” de grupos do dataset credit.
Com a solução do PAM para \(k=2\) grupos, tentamos interpretar o comportamento de cada cluster com a ajuda dos medoids da solução.
Tabela 14: Experimento 3 - Medoids da solução com k=2
load("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_euclidean.Rdata")
knitr::kable(credit[pam_2g$medoids, ])%>% kable_styling(position = "center")| ID | LIMITE | SEXO | ESCOLARIDADE | ESTADO.CIVIL | IDADE | HIST_SET2005 | HIST_AGO2005 | HIST_JUL2005 | HIST_JUN2005 | HIST_MAI2005 | HIST_ABR2005 | EXT_SET2005 | EXT_AGO2005 | EXT_JUL2005 | EXT_JUN2005 | EXT_MAI2005 | EXT_ABR2005 | PAG_SET2005 | PAG_AGO2005 | PAG_JUL2005 | PAG_JUN2005 | PAG_MAI2005 | PAG_ABR2005 | PAG_PADRAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 14580 | 14580 | 140000 | 2 | 2 | 1 | 34 | 0 | 0 | 0 | 0 | 0 | 0 | 15550 | 17780 | 18226 | 19915 | 20891 | 21542 | 2500 | 1500 | 2000 | 1300 | 1000 | 1500 | 0 |
| 27252 | 27252 | 230000 | 1 | 3 | 2 | 34 | 0 | 0 | 0 | 0 | 0 | 0 | 137122 | 138268 | 127797 | 130490 | 110153 | 112253 | 6700 | 6500 | 6513 | 4601 | 5000 | 5000 | 0 |
De acordo com a tabela, os clientes pertencentes ao grupo/cluster 1 têm as seguintes características: limite de NT$140k, mulheres casadas com graduação completa, idade média de 34 anos, utilizadoras de crédito rotativo em todos os meses, extratos entre NT$15k e NT$21k, diminuindo seus valores com o passar dos meses, pagamentos entre NT$1k e NT$2.5k e com comportamento irregular.
Os clientes do segundo grupo/cluster diferem são em geral homens solteiros, com limite de NT$230k, ensino médio completo, com mesma idade média, também utilizadores de crédito rotativo em todos os meses, extratos entre NT$110k e NT$140k, pagamentos entre NT$4.5k e NT$7k, e também apresentam comportamento irregular.
Verificando a matriz de confusão para a solução com \(k=2\), obtemos:
Tabela 15: Experimento 3 - Matriz de confusão para a solução com k=2
aux <- dois_grupos
aux<- as.character(aux[-1,])
# table(aux)
# 1 aparece em maior quantidade, logo, corresponde ao grupo 0 da base original
aux [which(aux=="1")] <- "0"
aux [which(aux=="2")] <- "1"
# correspondencia <- data.frame(PAG_PADRAO = sum(as.character(credit$PAG_PADRAO) == aux)/30000)
#
# correspondencia <- round(correspondencia*100,2)
# colnames(correspondencia) <- c(" Exp1 - Acertos (%)")
# knitr::kable(correspondencia)%>% kable_styling(position = "center")
#Creates vectors having data points
expected_value <- factor(aux)
predicted_value <- factor(credit$PAG_PADRAO)
#Creating confusion matrix
example <- confusionMatrix(data=predicted_value, reference = expected_value)
#Display results
knitr::kable(example$table)%>% kable_styling(position = "center")| 0 | 1 | |
|---|---|---|
| 0 | 18424 | 4940 |
| 1 | 5442 | 1194 |
- Na solução de agrupamento obtida, os objetos foram alocados aos clusters 1 e 2. Por possuir mais observações, tal qual o grupo 0 da base original, transformou-se o “1” em “0”. Logo, o “2” teve que ser transformado em “1”.
- Ao compararmos a variável PAG_PADRAO com a solução do agrupamento para \(k=2\) do Experimento 2, temos que a acurácia foi de 65.39%.
- De acordo com a tabela, o agrupamento obtido alocou um objeto pertencente ao grupo 0 originalmente ao grupo 0 do agrupamento em 18424 casos e alocou um objeto do grupo 0 ao grupo 1 em 5442 casos.
- O agrupamento obtido alocou um objeto pertencente ao grupo 1 originalmente ao grupo 0 do agrupamento em 4940 casos, e alocou um objeto do grupo 1 ao grupo 1 do agrupamento em 1194 casos.
Distância Euclidiana + CLARA
Por fim, o Experimento 4 também utilizou a distância Euclidiana, mas agora em conjunto ao algoritmo CLARA.
Comentamos anteriormente que a distância euclidiana deve ser usada somente com variáveis quantitativas, portanto, utilizamos neste experimento somente as variáveis quantitativas do dataset:
- LIMITE
- IDADE
- EXT_SET2005
- EXT_AGO2005
- EXT_JUL2005
- EXT_JUN2005
- EXT_MAI2005
- EXT_ABR2005
- PAG_SET2005
- PAG_AGO2005
- PAG_JUL2005
- PAG_JUN2005
- PAG_MAI2005
- PAG_ABR2005
Previamente ao cálculo das distâncias, essas variáveis foram padronizadas com o auxílio da função scale.
A matriz de distância foi obtida pela função distances do pacote distances.
Com a matriz de distâncias euclidiana em mãos, o Experimento 4 consistiu em aplicar o algoritmo de agrupamento CLARA variando o número de grupos k entre 2 e 5. A qualidade dos agrupamentos foi verificada através da silhueta média das soluções.
# i=2
# clara_clusters <- clara(credit[,c(2,6,13:24)], k=i, samples = 50,sampsize=1000, pamLike = TRUE, stand = FALSE)
# save(clara_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_euclidean_clara.Rdata")
# dois_grupos <- data.frame(c(as.vector(clara_clusters$silinfo$avg.width),as.vector(clara_clusters$clustering)))
# fwrite(dois_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_euclidean_clara.csv")
#
# rm(list=c("clara_clusters","dois_grupos"))
# gc()
#
# i=3
# clara_clusters <- clara(credit[,c(2,6,13:24)], k=i, samples = 50,sampsize=1000, pamLike = TRUE, stand = FALSE)
# save(clara_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_euclidean_clara.Rdata")
# tres_grupos <- data.frame(c(as.vector(clara_clusters$silinfo$avg.width),as.vector(clara_clusters$clustering)))
# fwrite(tres_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_euclidean_clara.csv")
#
# rm(list=c("clara_clusters","tres_grupos"))
# gc()
#
# i=4
# clara_clusters <- clara(credit[,c(2,6,13:24)], k=i, samples = 50,sampsize=1000, pamLike = TRUE, stand = FALSE)
# save(clara_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_euclidean_clara.Rdata")
# tres_grupos <- data.frame(c(as.vector(clara_clusters$silinfo$avg.width),as.vector(clara_clusters$clustering)))
# fwrite(quatro_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_euclidean_clara.csv")
#
# rm(list=c("clara_clusters","quatro_grupos"))
# gc()
#
# i=5
# clara_clusters <- clara(credit[,c(2,6,13:24)], k=i, samples = 50,sampsize=1000, pamLike = TRUE, stand = FALSE)
# save(clara_clusters,file="C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_euclidean_clara.Rdata")
# cinco_grupos <- data.frame(c(as.vector(clara_clusters$silinfo$avg.width),as.vector(clara_clusters$clustering)))
# fwrite(cinco_grupos, file = "C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_euclidean_clara.csv")
#
# rm(list=c("clara_clusters","cinco_grupos"))
# gc()
#
# rm(list = ls())
# gc()
# .rs.restartR()
dois_grupos<- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\doisgrupos_euclidean_clara.csv")
tres_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_euclidean_clara.csv")
quatro_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\quatrogrupos_euclidean_clara.csv")
cinco_grupos <- read.csv("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\cincogrupos_euclidean_clara.csv")
silhueta <- cbind.data.frame (grupos=as.factor(1:5),silhueta=c(0, dois_grupos[1,],tres_grupos[1,],quatro_grupos[1,],cinco_grupos[1,]))
ggplot(data=silhueta, aes(x=grupos, y=silhueta, group=1, label=as.character(round(silhueta,2)))) +
geom_line()+
geom_point()+
geom_text(hjust=0, vjust=-1.5)+
labs(x="\nGrupos",y="Valor da silhueta média\n", title="Experimento 4 - Valor da silhueta média de acordo com o número de grupos k\n")+
scale_y_continuous(breaks = seq(0,0.6,by=0.1), limits= c(0,0.6))+
theme_classic()Note que, de acordo com os valores da silhueta média, a melhor solução utilizando a distância de Euclidiana em conjunto ao algoritmo CLARA é para \(k=3\) grupos.
Com a solução do CLARA para \(k=3\) grupos, tentamos interpretar o comportamento de cada cluster com a ajuda dos medoids da solução.
Tabela 16: Experimento 4 - Medoids da solução com k=3
load("C:\\Users\\Victoria Vargas\\Downloads\\ATIVIDADE 3\\tresgrupos_euclidean_clara.Rdata")
knitr::kable(credit[clara_clusters$i.med, ])%>% kable_styling(position = "center")| ID | LIMITE | SEXO | ESCOLARIDADE | ESTADO.CIVIL | IDADE | HIST_SET2005 | HIST_AGO2005 | HIST_JUL2005 | HIST_JUN2005 | HIST_MAI2005 | HIST_ABR2005 | EXT_SET2005 | EXT_AGO2005 | EXT_JUL2005 | EXT_JUN2005 | EXT_MAI2005 | EXT_ABR2005 | PAG_SET2005 | PAG_AGO2005 | PAG_JUL2005 | PAG_JUN2005 | PAG_MAI2005 | PAG_ABR2005 | PAG_PADRAO | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 22435 | 22435 | 60000 | 2 | 3 | 2 | 45 | 0 | 0 | 0 | 0 | 0 | 0 | 26350 | 23908 | 24215 | 17728 | 18087 | 17730 | 1413 | 1500 | 1173 | 532 | 597 | 469 | 0 |
| 19731 | 19731 | 200000 | 2 | 3 | 1 | 39 | -1 | 0 | 0 | 0 | 0 | 0 | 145687 | 146519 | 144315 | 130807 | 124688 | 122518 | 7627 | 4631 | 5066 | 5033 | 5007 | 5125 | 0 |
| 14890 | 14890 | 260000 | 1 | 2 | 2 | 30 | 0 | 0 | 0 | 0 | 0 | 0 | 7426 | 6887 | 7757 | 8172 | 8407 | 8681 | 2000 | 1757 | 2000 | 2000 | 2000 | 2000 | 0 |
Grupo/cluster 1: Limite de NT$60k, mulheres casadas com ensino médio completo e idade média de 39 anos, utilizando crédito rotativo em todos os meses de análise, extratos entre NT$17k e NT$27k, pagamentos por volta de NT$500 até junho e com média de NT$1.3k nos meses restantes e com comportamento irregular.
Grupo/cluster 2: Limite de NT$200k, mulheres solteiras com ensino médio completo e idade média de 45 anos, utilizando crédito rotativo com exceção do mês de setembro, extratos entre NT$12k e NT$15k, pagamentos entre NT$4k e NT$8k e com comportamento irregular.
Grupo/cluster 3: Limite de NT$260k, homens casados com graduação completa e idade média de 30 anos, utilizando crédito rotativo em todos os meses de análise, extratos entre NT$6k e NT$9k, pagamentos iguais a NT$2k em todos os meses com exceção de agosto, e com comportamento irregular.
Verificando a matriz de confusão para a solução com \(k=2\), obtemos:
Tabela 17: Experimento 4 - Percentual de acerto para a solução com k=2
aux <- dois_grupos
aux<- as.character(aux[-1,])
# table(aux)
# aux [which(aux=="1")] <- "0"
# aux [which(aux=="2")] <- "1"
aux [which(aux=="2")] <- "0"
# correspondencia <- data.frame(PAG_PADRAO = sum(as.character(credit$PAG_PADRAO) == aux)/30000)
#
# correspondencia <- round(correspondencia*100,2)
# colnames(correspondencia) <- c(" Exp1 - Acertos (%)")
# knitr::kable(correspondencia)%>% kable_styling(position = "center")
#
#Creates vectors having data points
expected_value <- factor(aux)
predicted_value <- factor(credit$PAG_PADRAO)
#Creating confusion matrix
example <- confusionMatrix(data=predicted_value, reference = expected_value)
#Display results
knitr::kable(example$table)%>% kable_styling(position = "center")| 0 | 1 | |
|---|---|---|
| 0 | 11515 | 11849 |
| 1 | 2162 | 4474 |
- Na solução de agrupamento obtida, os objetos foram alocados aos clusters 1 e 2. Por possuir mais observações, tal qual o grupo 0 da base original, transformou-se o “1” em “0”. Logo, o “2” teve que ser transformado em “1”.Nessa configuração, ao compararmos a variável PAG_PADRAO com a solução do agrupamento para \(k=2\) do Experimento 2, temos que a acurácia foi de 46.7%. Então, de forma a maximizar a acurácia, optamos por transformar o cluster “2” em “0”, mantendo o cluster 1, obtendo uma acurácia de 53.3%.
- De acordo com a tabela, o agrupamento obtido alocou um objeto pertencente ao grupo 0 originalmente ao grupo 0 do agrupamento em 11515 casos e alocou um objeto do grupo 0 ao grupo 1 em 2162 casos.
- O agrupamento obtido alocou um objeto pertencente ao grupo 1 originalmente ao grupo 0 do agrupamento em 11849 casos, e alocou um objeto do grupo 1 ao grupo 1 do agrupamento em 4474 casos.
Conclusão
De acordo com as acurácias de cada método, o que teve maior porcentagem foi o da distância Euclidiana + PAM, e também, o que apresentou valores de silhueta média mais divergentes.
Todos os métodos utilizados tiveram mais 50% de acurácia.
O experimento 2 foi o que teve os valores de silhueta média mais altos e mais pariformes entre si.
Com as melhores soluções de acordo com cada método, conseguimos utilizar os medoids para traçar o perfil representativo de cada cluster obtido.
Limitações
Como o dataset possui muitas observações, ao optar por utilizar a distância de Gower foi necessário calcular uma matriz de distância de grandes dimensões (30.000 x 30.000), o que demandou um poder de processamento mais elevado.
Foi utilizado um computador com as seguintes características para conduzir o cálculo dessa matriz e em seguida, utilizá-la como dado de entrada nos demais algoritmos:
Processador i5-9400f 4.0GHz Memória RAM 16Gb DDR4 2666 Mhz SSD 240 Gb
A cada etapa do trabalho foi necessário salvar os outputs das funções para posterior uso, a fim de economizar tempo e garantir o que foi feito.
Para arquivos grandes, as funções fwrite do pacote data.table e saveRDS foram utilizadas para agilizar o salvamento.
Para os experimentos envolvendo distância euclidiana, a função distances foi empregada e, por ser otimizada, não ocorreram dificuldades quanto à utilização de memória.
Foi cogitado a visualização dos clusters utilizando o T-Sne, entretanto, a função Rtsne do pacote Rtsne não aceita objetos produzidos pela função distances. A visualização pela matriz de Gower seria possível, mas o acesso ao computador utilizado nos cálculos era limitado e os computadores disponíveis nesse momento do trabalho não possuíam poder de processamento suficiente sequer para a leitura do arquivo.
Referências
L. Kaufman and P. J. Rousseeuw. Finding Groups in Data - An Introduction to Clusters Analysis. Wiley-Interscience Publication, 1989.
W. B. Hair and B. A. R. Babin. Multivariate Data Analysis. Cengage, 8th edition, 2018.