ALGORITMOS DE AGRUPAMENTO EM DADOS SÓCIO-ECONÔMICOS DOS PAÍSES

Introdução

Problema

Agrupar países de acordo com indicadores sócio-econômicos.

Serão aplicados três algoritmos de clusterização a fim de verificar o que tem melhor desempenho: K-Means, agrupamento hierárquico e DBScan.

Pacotes

library(factoextra)
library(fpc)
library(dbscan)
library(cluster)
library(factoextra)
library(DT)
library(ggplot2)
library(dplyr)
library(tidyr)
library(ggcorrplot)

Dataset

Conjunto de dados com indicadores de 167 países.

data<-read.csv('dataset/dados.csv', row.names = 1)
DT::datatable(data, options = list(scrollX = TRUE, scrollCollapse = TRUE))

Inspeção e tratamento

O dataset já está pré-processado, mas ainda deve ser feito o escalonamento das variáveis, pois os algoritmos aplicados são baseados em distâncias.

Tipo de variáveis

Variáveis todas numéricas, como se espera em um problema de agrupamento.

str(data)
'data.frame':   167 obs. of  9 variables:
 $ child_mort: num  90.2 16.6 27.3 119 10.3 14.5 18.1 4.8 4.3 39.2 ...
 $ exports   : num  10 28 38.4 62.3 45.5 18.9 20.8 19.8 51.3 54.3 ...
 $ health    : num  7.58 6.55 4.17 2.85 6.03 8.1 4.4 8.73 11 5.88 ...
 $ imports   : num  44.9 48.6 31.4 42.9 58.9 16 45.3 20.9 47.8 20.7 ...
 $ income    : int  1610 9930 12900 5900 19100 18700 6700 41400 43200 16000 ...
 $ inflation : num  9.44 4.49 16.1 22.4 1.44 20.9 7.77 1.16 0.873 13.8 ...
 $ life_expec: num  56.2 76.3 76.5 60.1 76.8 75.8 73.3 82 80.5 69.1 ...
 $ total_fer : num  5.82 1.65 2.89 6.16 2.13 2.37 1.69 1.93 1.44 1.92 ...
 $ gdpp      : int  553 4090 4460 3530 12200 10300 3220 51900 46900 5840 ...

Escalonamento

Escalonamento por padronização com média 0 e desvio padrão 1, guardando média e desvio padrão para poder reverter os valores posteriormente.

mean_data<-sapply(data, mean) 
sd_data<-sapply(data, sd)
data<-as.data.frame(scale(data))
head(data)
                    child_mort     exports      health     imports      income
Afghanistan          1.2876597 -1.13486665  0.27825140 -0.08220771 -0.80582187
Albania             -0.5373329 -0.47822017 -0.09672528  0.07062429 -0.37424335
Algeria             -0.2720146 -0.09882442 -0.96317624 -0.63983800 -0.22018227
Angola               2.0017872  0.77305618 -1.44372888 -0.16481961 -0.58328920
Antigua and Barbuda -0.6935483  0.16018613 -0.28603389  0.49607554  0.10142673
Argentina           -0.5894047 -0.81019144  0.46756001 -1.27594958  0.08067776
                     inflation life_expec   total_fer        gdpp
Afghanistan          0.1568645 -1.6142372  1.89717646 -0.67714308
Albania             -0.3114109  0.6459238 -0.85739418 -0.48416709
Algeria              0.7869076  0.6684130 -0.03828924 -0.46398018
Angola               1.3828944 -1.1756985  2.12176975 -0.51472026
Antigua and Barbuda -0.5999442  0.7021467 -0.54032130 -0.04169175
Argentina            1.2409928  0.5897009 -0.38178486 -0.14535428

Análise exploratória dos dados

Estatística descritiva

summary(data)
   child_mort         exports            health           imports       
 Min.   :-0.8845   Min.   :-1.4957   Min.   :-1.8223   Min.   :-1.9341  
 1st Qu.:-0.7444   1st Qu.:-0.6314   1st Qu.:-0.6901   1st Qu.:-0.6894  
 Median :-0.4704   Median :-0.2229   Median :-0.1805   Median :-0.1483  
 Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
 3rd Qu.: 0.5909   3rd Qu.: 0.3736   3rd Qu.: 0.6496   3rd Qu.: 0.4899  
 Max.   : 4.2086   Max.   : 5.7964   Max.   : 4.0353   Max.   : 5.2504  
     income          inflation         life_expec        total_fer      
 Min.   :-0.8577   Min.   :-1.1344   Min.   :-4.3242   Min.   :-1.1877  
 1st Qu.:-0.7153   1st Qu.:-0.5649   1st Qu.:-0.5910   1st Qu.:-0.7616  
 Median :-0.3727   Median :-0.2263   Median : 0.2861   Median :-0.3554  
 Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
 3rd Qu.: 0.2934   3rd Qu.: 0.2808   3rd Qu.: 0.7021   3rd Qu.: 0.6157  
 Max.   : 5.5947   Max.   : 9.1023   Max.   : 1.3768   Max.   : 3.0003  
      gdpp         
 Min.   :-0.69471  
 1st Qu.:-0.63475  
 Median :-0.45307  
 Mean   : 0.00000  
 3rd Qu.: 0.05924  
 Max.   : 5.02140  

Distribuição das variáveis

data_gather <- data %>%
  as_data_frame() %>%
  gather(key = "variable", value = "value")

ggplot(data_gather, aes(value)) +
  geom_density() +
  facet_wrap(~variable)

Correlações

tabcor<-cor(data)
ggcorrplot(tabcor, lab=TRUE, type = "lower")

Algoritmos

K-Means

Elbow method

Uso do “método do cotovelo” com a soma dos quadrados intracluster. O resultado da visualização é um tanto ambíguo, mas k=4 parece uma escolha razoável.

fviz_nbclust(data, FUNcluster = kmeans, method = "wss")

Implementação

kmeans_clusters <- eclust(data, FUNcluster = 'kmeans' , k = 4, graph = FALSE)
# Resultado
kmeans_clusters$centers
  child_mort      exports       health     imports     income   inflation
1 -0.8261247  0.172103053  0.856613486 -0.29548409  1.4578905 -0.47675466
2 -0.4185681  0.006628559 -0.211088772  0.04743879 -0.2166227 -0.03484844
3  1.3561391 -0.436221182 -0.155516293 -0.18863644 -0.6848344  0.40090504
4 -0.8464575  4.920873128 -0.008138555  4.53442030  2.4322274 -0.50269428
  life_expec  total_fer       gdpp
1  1.1043279 -0.7613916  1.6569189
2  0.2676147 -0.4369082 -0.3298134
3 -1.2783352  1.3608511 -0.6024306
4  1.2231457 -1.0357477  2.4334786
#Cada país agrupado num cluster com rótulo 1, 2, 3 ou 4.
head(kmeans_clusters$cluster,8)
        Afghanistan             Albania             Algeria              Angola 
                  3                   2                   2                   3 
Antigua and Barbuda           Argentina             Armenia           Australia 
                  2                   2                   2                   1 
#Tamanho de cada cluster.
kmeans_clusters$size
[1] 30 87 47  3

Visualização

Gráfico, usando PCA, para visualizar os grupos em duas dimensões. Por falta de espaço, nem todos os países são exibidos.

fviz_cluster(kmeans_clusters, geom='text', xlab='', ylab='', main='K-Means', 
             labelsize=10, repel=TRUE)

Avaliação

Método da silhueta para avaliar a qualidade do agrupamento. Como os resultados mostram, o k-means teve bom desempenho. No entanto, a Coréia do Sul e alguns países que estão na vizinhança entre os grupos 2 e 3, como Botswana, conforme já sugeria a visualização acima, podem ter sido classificados errado.

kmeans_silhouette<-kmeans_clusters$silinfo
head(kmeans_silhouette$widths[order(kmeans_silhouette$widths$sil_width),],10)
             cluster neighbor    sil_width
Botswana           3        2 -0.079653471
Iraq               3        2 -0.068529312
South Korea        1        2 -0.048579689
Namibia            3        2 -0.022262588
South Africa       3        2 -0.011982782
Lao                3        2  0.002380055
Gabon              3        2  0.035521674
Kiribati           3        2  0.041619782
Cyprus             1        2  0.045731665
Bahamas            2        1  0.059603555
fviz_silhouette(kmeans_clusters)
  cluster size ave.sil.width
1       1   30          0.30
2       2   87          0.33
3       3   47          0.25
4       4    3          0.39

Agrupamento hierárquico

Implementação

Usando os principais métodos aglomerativos.

Ward1
#Implementação
hc_ward1 <- eclust(data, FUNcluster = 'hclust', hc_method='ward.D')
#Dendograma
fviz_dend(hc_ward1, main="Ward1", cex = 0.6)

Análise por silhueta

Como se oberva, os resultados são inferiores ao k-means, com mais erros de classificação e, em média, valores menores de silhueta.

fviz_silhouette(hc_ward1)
  cluster size ave.sil.width
1       1   65          0.15
2       2   68          0.38
3       3   34          0.08

Ward2
#Implementação
hc_ward2 <- eclust(data, FUNcluster = 'hclust', hc_method='ward.D2')
#Dendograma
fviz_dend(hc_ward2, main="Ward2", cex = 0.6)

Análise por silhueta

Ward2 se saiu melhor que Ward1, mas ainda inferior aos resultados do k-means.

fviz_silhouette(hc_ward2)
  cluster size ave.sil.width
1       1   27          0.45
2       2  106          0.21
3       3   34          0.19

Single linkage

O single linkage não conseguiu discriminar bem os grupos, deixando praticamente todos os países num cluster só.

#Implementação
hc_sl <- eclust(data, FUNcluster = 'hclust', hc_method='single')
#Dendograma
fviz_dend(hc_sl, main="Single linkage", cex = 0.6)

Análise por silhueta
fviz_silhouette(hc_sl)
  cluster size ave.sil.width
1       1  165          0.58
2       2    1          0.00
3       3    1          0.00

Complete linkage
#Implementação
hc_cl <- eclust(data, FUNcluster = 'hclust', hc_method='complete')
#Dendograma
fviz_dend(hc_cl, main="Complete linkage", cex = 0.6)

Análise por silhueta

Foi o melhor dos 4 métodos aglomerativos, ainda assim inferior ao k-means.

fviz_silhouette(hc_cl)
  cluster size ave.sil.width
1       1   55          0.27
2       2  109          0.30
3       3    3          0.43

DBScan

Será utilizado um número mínimo de 3 pontos na região do epsilon para que a observação seja colocada no grupo. Para a definição do epsilon, o pacote dbscan oferece o gráfico kNNdistplot, um gráfico de distâncias para o kNN que pode ser utilizado para definir o melhor epsilon do dbscan observando onde fica o “joelho” da curva. 2 parece um bom epsilon.

minpts<-3
kNNdistplot(data, k =  minpts)
abline(h = 2)

#Implementação
dbscan_cluster<-fpc::dbscan(data, eps=2, MinPts =minpts)
#Grupos
table(dbscan_cluster$cluster)

  0   1 
  6 161 

Vê-se que, a exemplo do método single linkage, no agrupamento hierárquico, as observações ficaram num só grupo (0 é não classificado). Considerando que os dados foram padronizados com média 0 e desvio padrão 1, epsilon=2 pode ser grande demais para que o algoritmo consiga discriminar mais grupos. Reduzindo o valor de epsilon para 1, o algoritmo forma mais clusters, mas não consegue classificar 72 observações, o que é muito para um conjunto de 163 países.

dbscan_cluster<-fpc::dbscan(data, eps=1, MinPts =minpts)
table(dbscan_cluster$cluster)

 0  1  2  3  4  5  6 
72  8 59 16  4  5  3 

Conclusão

Conforme os resultados acima, o algoritmo de melhor desempenho em separar os países por clusters é o k-means com 4 grupos. Os demais algortimos ou não se saíram tão bem em colocar cada país no grupo correto, ou foram incapazes de formar mais do que um cluster e rotular todas as observações.