OBJETIVO: identificar municípios similares. Colocando de outra forma: dentro do conjunto total de municípios em questão, será que existem subgrupos de municípios similares?
Tal “similaridade” será obtida utilizando as variáveis disponíveis no conjunto de dados (doravante dataset).
FERRAMENTA UTILIZADA: ANÁLISE DE AGRUPAMENTOS (CLUSTER ANALYSIS)
Para não depender de arquivos externos, vamos criar a tabela de dados “na mão”1. O código para este procedimento manual está abaixo:
raw_data_alt <- data.frame(Municipio=c("Cambe","Ibipora","Londrina","Pitangueiras","Rolandia","Tamarana"),
PopTotal=c(88186,42153,447065,2418,49410,9713),
EVN=c(72.87,74.43,71.37,72.25,68.4,66.57),
TxAlfab=c(90.55,88.8,92.93,84.97,90.48,77.26),
row.names = 1)Um aspecto importante para a construção do dendograma é que precisamos de nomes de linhas no dataset. Isto não é muito frequente em outros tipos de análises estatísticas, mas para a utilização da função do R hclust(), que cria efetivamente os agrupamentos hierárquicos (doravante HC), os nomes das linhas são fundamentais. No R, isto é feito usando o argumento row.names. Mas isto não será necessário neste caso pois já criamos nosso dataset from scratch. Mas, por exemplo, se tivéssemos por acaso o arquivo salvo como “exerc_cluster.csv”, poderíamos carregar o arquivo da seguinte forma:
path <- paste0("D:\\PANDORA\\backup_pen_2017-02-27\\",
"posgrad_Geoprocessamento\\",
"Disciplina_05_Metodos_Quantitativos_Geografia\\",
"Unidade 04 - Introdução à Análise de Agrupamentos")
setwd(path)
raw_data <- read.csv("exerc_cluster.csv", sep=" ",
dec=",", row.names = 1)Para verificar se a importação foi bem-sucedida, vamos executar alguns comandos:
raw_data_alt # Visualiza os dados em forma tabular organizadasummary(raw_data_alt) # visualiza o "resumo dos '6' números".## PopTotal EVN TxAlfab
## Min. : 2418 Min. :66.57 Min. :77.26
## 1st Qu.: 17823 1st Qu.:69.14 1st Qu.:85.93
## Median : 45782 Median :71.81 Median :89.64
## Mean :106491 Mean :70.98 Mean :87.50
## 3rd Qu.: 78492 3rd Qu.:72.72 3rd Qu.:90.53
## Max. :447065 Max. :74.43 Max. :92.93
Esta saída mostra claramente que as variáveis possuem centralidade e variabilidades bem distintas. Outra forma interessante de se visualizar isto é com side-by-side boxplots:
boxplot(raw_data_alt)Desta forma, vamos padronizar o conjunto de dados antes de proceder ao HC.
A função scale() do R, com seus argumentos-padrão, faz exatamente a conta que foi aprendida no processo de padronização:
\[{\Large X_{Pad} = \frac{X-E(X)}{\sigma_X}}\] Na fórmula acima, \(X_{Pad}\) é a variável \(X\) padronizada, \(E(X)\) denota a Esperança (ou “média”) de \(X\), e \(\sigma{X}\) denota o desvio padrão de \(X\). As notações referem-se aos parâmetros populacionais da variável aleatória devido ao comentário feito pelo prof. Bernardo sobre amostras no contexto geográfico (amostra \(\equiv\) população).
Podemos fazer uma simulação no R e verificar que isto realmente acontece, ou seja, que a função scale() funciona da forma que desejamos:
set.seed(31415)
# para reprodutibilidade do exemplo, precisamos gerar uma semente
simula <- rnorm(10, mean=50, sd=5)
# Simula 10 variáveis aleatórias normais com média 5 e desv.pad.5
simula_scaled <- (simula-mean(simula))/sd(simula)
# Cálculo-padrão feito para padronizar o vetor `simula`
simula_scaled2 <- as.vector(scale(simula))
# Utilizando a função pronta (built-in) do R `scale()`
cbind(simula_scaled, simula_scaled2)## simula_scaled simula_scaled2
## [1,] 1.2622143 1.2622143
## [2,] -0.9009903 -0.9009903
## [3,] -1.2432756 -1.2432756
## [4,] -0.6159015 -0.6159015
## [5,] 1.1676560 1.1676560
## [6,] -0.9213273 -0.9213273
## [7,] 0.5687370 0.5687370
## [8,] 0.6699789 0.6699789
## [9,] -0.9115004 -0.9115004
## [10,] 0.9244089 0.9244089
# Visualizando os dois vetores, simula_scaled e simula_scaled2
# lado a lado
identical(simula_scaled, simula_scaled2)## [1] TRUE
# Testa se 2 objetos são extamente iguaisAgora que sabemos que scale() funciona da forma que desejamos, podemos aplicá-la em nossos dados:
data_scaled <- scale(raw_data_alt)Vamos agora, de fato, executar o algoritmo HC, com distância euclidiana. Os métodos utilizados para obter as distâncias entre dois clusters ou entre uma observação(“ponto”) e um cluster (cada método de cálculo destas distâncias são definidos na literatura como linkage, e doravante utilizaremos este termo) serão2:
A função que executa o algoritmo de HC no R (pacote base) é hclust(). O input desta função é uma matriz de distâncias, que no R pode ser obtida pela função dist(). Podemos visualizar a matriz de distancias antes de executar o HC e plotar os dendogramas:
dist(data_scaled)## Cambe Ibipora Londrina Pitangueiras Rolandia
## Ibipora 0.6705853
## Londrina 2.2159361 2.7031671
## Pitangueiras 1.1265810 1.0294242 2.9884008
## Rolandia 1.5353520 2.0698162 2.5880576 1.6527839
## Tamarana 3.2079187 3.3628637 4.1166716 2.3609343 2.4252051
A seguir estão os comandos que executam o algoritmo HC com distância Euclidiana e os três tipos de linkage citados. Além disso, construímos, lado a lado, três dendogramas, correspondentes a cada tipo de linkage:
mun.hc.complete <- hclust(dist(data_scaled), method="complete")
mun.hc.average <- hclust(dist(data_scaled), method="average")
mun.hc.single <- hclust(dist(data_scaled), method="single")
par(mfrow=c(1,3))
plot(mun.hc.complete, main="Complete Linkage", xlab="", sub="",
cex=.9)
plot(mun.hc.average, main="Average Linkage", xlab="", sub="",
cex=.9)
plot(mun.hc.single, main="Single Linkage", xlab="", sub="",
cex=.9)Os dendogramas foram criados, mas podem ser melhorados alinhando o texto de todas as observações (municípios no caso) na base da escala do eixo vertical:
par(mfrow=c(1,3))
plot(mun.hc.complete, main="Complete Linkage", xlab="", sub="",
cex=.9, hang=-1)
plot(mun.hc.average, main="Average Linkage", xlab="", sub="",
cex=.9, hang=-1)
plot(mun.hc.single, main="Single Linkage", xlab="", sub="",
cex=.9, hang=-1)par(mfrow=c(1,1)) # Não se preocupe com esta linha do códigoConstruídos os dendogramas, a determinação do número de clusters fica a cargo do analista. Em geral, tentamos várias possibilidades. No caso do nosso exercício, temos apenas 6 municípios e os três linkages exibem dendogramas com padrões muito parecidos. Destarte, nos comandos a seguir vamos nos focar no Average Linkage, e testar o que ocorre quando escolhemos 2, 3 e 4 clusters. Vamos fazer três dendogramas lado a lado (todos usando Average Linkage) e fazer cortes no dendograma para indicar o número de clusters:
par(mfrow=c(1,3))
plot(mun.hc.average, main="HC - Corte em 2 Clusters", xlab="", sub="",
cex=.9, hang=-1)
abline(h=3, lty=2, lwd=2, col = "#E31A1C")
plot(mun.hc.average, main="HC - Corte em 3 Clusters", xlab="", sub="",
cex=.9, hang=-1)
abline(h=2.5, lty=2, lwd=2, col = "#E31A1C")
plot(mun.hc.average, main="HC - Corte em 4 Clusters", xlab="", sub="",
cex=.9, hang=-1)
abline(h=1.5, lty=2, lwd=2, col = "#E31A1C")Considerando distância euclidiana e average linkage, temos então:
Com 2 clusters, a solução HC fica {Tamarana}, {Londrina, Rolândia, Pitangueiras, Cambé, Ibiporã};
Com 3 clusters, a solução HC fica {Tamarana}, {Londrina}, {Rolândia, Pitangueiras, Cambé, Ibiporã};
Com 4 clusters, a solução HC fica {Tamarana}, {Londrina}, {Rolândia}, {Pitangueiras, Cambé, Ibiporã}.
Partindo de um exemplo simples, com poucas obsevações, construímos uma Análise de Conglomerados segundo o método Hierárquico. Tal método é bastante intuitivo, seu algoritmo é bem simples e podemos construir uma representação gráfica muito atraente, o Dendograma. No HC, o analista deve levar em conta o tipo de medida de (dis)similaridade, o tipo de linkage, bem como levar em conta o número de clusters a ser definido.
O Pacote R é muito poderoso e possui extensas ferramentas que podem fazer esta análise de agrupamentos e construir dendogramas avançadíssimos. Apenas para citar alguns pacotes que constroem dendogramas:
Se quiser saber mais sobre os pacotes do R que controem dendogramas, faça uma busca no site do CRAN e examine os pacotes disponíveis (vá com fôlego, pois no momento em que escrevo - 2017-09-23 existem 11486 pacotes disponíveis). Visite este endereço.
O R é muito mais que apenas um pacote estatístico, ele te ensina muito sobre estatística e te mantém atualizado sobre os avanços em uitas das suas sub-áreas e áreas correlatas. Em particular, o CRAN possui as chamadas Task Views, pacotes relacionados a determinadas áreas da Estatística e correlatas. Atualmente, existem 35 Task Views. Dentre elas, existe a Task View Cluster. Vá em frente e veja o que pode encontrar de interessante.
Por fim, uma excelente fonte de informações é o site R-bloggers, um agregador de novidades e tutoriais de mais de 750 sites sobre R.
[1] Chang, W. R Graphics Cookbook. O’Reilly, 2013.
[2] Galili, T. dendextend: an R package for visualizing, adjusting, and comparing trees of hierarchical clustering. In “Bioinformatics”. doi 10.1093/bioinformatics/btv428. url: http://bioinformatics.oxfordjournals.org/content/31/22/3718. 2015. eprint: http://bioinformatics.oxfordjournals.org/content/31/22/3718.full.pdf+html.
[3] James, G. et al. An Introduction to Statistical Learning: with Applications in R. Springer, 2013.
[4] R Core Team. R: A Language and Environment for Statistical Computing. Vienna, 2017. url: https://www.R-project.org/
Em geral, este não é um procedimento recomendado em análise de dados, pois os conjuntos de dados (em geral) são extensos, podem estar indexados quando pertencem a bases de dados, cada variável pode ter classes e tamanhos determinados e outra série de complicações que tornam este procedimento desaconselhável, sem contar a possibilidade de falha humana nesta operação praticamente “manual”. Aqui, optamos por este caminho pelo motivo já citado.↩
existem muitos e muitos tipos de linkage. Um deles é simples o bastante para ser citado aqui: centroide, que consiste em obter o centroide (media aritmetica) de cada cluster, e daí a distancia intercluster será a distância entre os centroides.↩