Atividade Computacional 1

Três classificadores foram implementados em R para esta atividade:

O desempenho de cada um dos classificadores foi verificado sobre o banco de dados parkinsons, disponível em:

https://archive.ics.uci.edu/ml/datasets/Parkinsons


Medidas como média, mediana, amplitude, desvio padrão foram calculadas a partir de 100 execuções de cada classificador, assim como a média da sensibilidade e especificidade. No caso do classificador Gaussiano foram usados dois métodos de regularização para a matriz de covariância de cada classe, visto que elas não se mostraram invertíveis. O posto calculado para as matrizes de covariância de cada classe foi 19 e sua ordem 22 o que confirma sua singularidade.

Os métodos utilizados para regularização foram:

Os algoritmos também foram avaliados sob a redução de dimensionalidade dos dados. Para isso foram utilizados dois métodos de redução:

Para as componentes principais, os dados foram reduzidos a 2 componentes que carregam em si 94.7% (72.9% para componente 1 e 21.8% para componente 2) da variabilidade total dos dados.

O gráfico abaixo apresenta a fração da variabilidade total dos dados que cada componente principal carrega em si.

figura 01

Porém o método não se mostrou eficaz para melhorar o desempenho dos classificadores visto que, mesmo com a redução de dimensão, não foi possível distinguir claramente uma divisão entre as classes.

figura 02

Já ao aplicar o discriminante linear de Fisher nos dados, houve uma melhora em todas as medidas de desempenho para cada um dos classificadores. Esse ganho no desempenho pode ser atribuido ao fato de que podemos observar uma separação mais clara dos dados transformados pelo discriminante linear.

A figura abaixo apresenta o gráfico de dispersão para os dados.

figura 03

Abaixo segue a tabela com os resultados obtidos a partir de 100 execuções de cada algoritmo de classificação juntamente com as reduções de dimensionalidade e os métodos de regularização:

Classificador Média Mediana Mínimo Máximo Desvio Padrão Sensibilidade Especificidade
NN 0.830 0.840 0.731 0.910 0.035 0.892 0.651
NN+LDA 0.863 0.873 0.770 0.936 0.036 0.913 0.706
NN+PCA 0.811 0.808 0.744 0.885 0.033 0.871 0.625
DMC 0.708 0.705 0.615 0.872 0.043 0.740 0.608
DMC+LDA 0.862 0.865 0.795 0.949 0.029 0.887 0.785
DMC+PCA 0.708 0.705 0.615 0.872 0.044 0.739 0.610
CQG+POOL 0.816 0.821 0.731 0.936 0.036 0.850 0.711
CQG+POOL+LDA 0.862 0.865 0.795 0.949 0.029 0.887 0.785
CQG+POOL+PCA 0.685 0.692 0.577 0.795 0.042 0.754 0.471
CQG+FRIEDMAN 0.839 0.846 0.744 0.923 0.036 0.865 0.758
CQG+FRIEDMAN+LDA 0.853 0.860 0.782 0.949 0.031 0.867 0.802
CQG+FRIEDMAN+PCA 0.652 0.654 0.526 0.782 0.05 0.705 0.485

Assim o classificador quadrático gaussiano, utilizando-se da regularização de Friedman para a matriz de covariância e juntamente com a redução de dimensionalidade obtida pelo discriminante linear de Fisher, foi o algoritmo que apresentou melhor desempenho.

Abaixo o códigos para cada um dos classificadores.

Classificadores

Vizinho mais Próximo (Nearest Neighbor)

library(tidyverse) # Biblioteca para manipulação de dados
library(pracma)    # Biblioteca para calculo da norma
library(caret)     # Biblioteca para o calculo de medidas de desempenho do classificador

data <- read.csv("~/Documentos/disciplinas/reconhecimento/codes/parkinson.csv", header=FALSE)
data <- data %>% mutate(id = row_number())

# Semente para reprodução dos resultados
set.seed(368651)

# Inicializando variaveis que armazenaram a acuracia, sensibilidade e especificidade
acu <- c()
sen <- c()
esp <- c()

for (k in 1:100) {
  # Separando o conjunto de dados em treino e teste
  treino_1 <- data %>% group_by(V23) %>% sample_frac(.6)
  teste_1  <- anti_join(data, treino_1, by = 'id')
  # Removendo as colunas de classe e id
  treino_2 <- treino_1[,-23]
  teste_2 <- teste_1[,-23]
  # Inicializando as variaveis distancia e classe
  d <- c()
  classe <- c()
  # Calculando as distancias de cada linha do teste para todas as linhas do treino
  for (i in 1:nrow(teste_2)) {
    for(j in 1:nrow(treino_2)){
      d[j] <- Norm(as.matrix(teste_2[i, ] - treino_2[j, ]))
    }
    classe[i] <- treino_1$V23[which.min(d)] # Classificando cada linha do teste
  }
  
  predito <- factor(classe) # Transformando a variavel classe em fator para usar a funcao confusionMatrix
  observado <- factor(teste_1$V23) # Criando a variavel observado em fator para usar a funcao confusionMatrix
  
  # Armazenando o resultado de cada rodada nas variaveis
  acu[k] <- confusionMatrix(predito, observado, positive = "1")$overall[[1]]
  sen[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[1]]
  esp[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[2]]
  
  cat("Rodada:", k, "\n")
}

##################################################################
##                          RESULTADOS                          ##
##################################################################
media <- mean(acu)
mediana <- median(acu)
min <- min(acu)
max <- max(acu)
desvio <- sd(acu)
media_sense <- mean(sen)
media_espec <- mean(esp)
mediana_sense <- median(sen)
mediana_espec <- median(esp)

# Criando uma tabela com as medidas descritivas
tab <- rbind(media,mediana,min,max,desvio,media_sense,media_espec, mediana_sense, mediana_espec); tab

Distância Mínima ao Centróide (Minimum Centroid Distance)

library(tidyverse) # Biblioteca para manipulação de dados
library(pracma)    # Biblioteca para calculo da norma
library(caret)     # Biblioteca para o calculo de medidas de desempenho do classificador

dados <- read.csv("~/Documentos/disciplinas/reconhecimento/codes/parkinson.csv", header=FALSE)
dados <- dados %>% mutate(id=row_number())

# Semente para reprodução dos resultados
set.seed(368651)

# Inicializando variaveis que armazenaram a acuracia, sensibilidade e especificidade
acu <- c()
sen <- c()
esp <- c()

for(k in 1:100){
# Separando o conjunto de dados em treino e teste
treino <- dados %>% group_by(V23) %>% sample_frac(.6)
teste  <- anti_join(dados, treino, by='id')
# Calculo dos centroides de cada classe
cent_1 <- treino[,-ncol(treino)] %>% filter(V23==0) %>% summarise_all(mean)
cent_2 <- treino[,-ncol(treino)] %>% filter(V23==1) %>% summarise_all(mean)
centroides <- list(cent_1[,-1], cent_2[,-1])
# Inicializando as variaveis distancia e classe
d <- c()
classe <- c()
# Calculando as distancias de cada linha do teste para todas as linhas do treino
for(i in 1:nrow(teste)){
    for(j in 1:2){
        d[j] <- Norm(as.matrix(teste[i,-c(23,24)] - centroides[[j]]))
    }
    if (which.min(d) == 1) {
        classe[i] <- 0
    } else {
        classe[i] <- 1
    }
}

  predito <- factor(classe) # Transformando a variavel classe em fator para usar a funcao confusionMatrix
  observado <- factor(teste$V23) # Criando a variavel observado em fator para usar a funcao confusionMatrix
  
  # Armazenando o resultado de cada rodada nas variaveis
  acu[k] <- confusionMatrix(predito, observado, positive = "1")$overall[[1]]
  sen[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[1]]
  esp[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[2]]
  
  cat("Rodada:", k, "\n")
}

##################################################################
##                          RESULTADOS                          ##
##################################################################
media <- mean(acu)
mediana <- median(acu)
min <- min(acu)
max <- max(acu)
desvio <- sd(acu)
media_sense <- mean(sen)
media_espec <- mean(esp)
mediana_sense <- median(sen)
mediana_espec <- median(esp)

# Criando uma tabela com as medidas descritivas
tab <- rbind(media,mediana,min,max,desvio,media_sense,media_espec, mediana_sense, mediana_espec); tab

Classificador Quadrático Gaussiano (Gaussian Quadratic Classifier) usando a matriz de covariância agregada (pooled covariance matrix)

library(tidyverse) # Biblioteca para manipulação de dados
library(pracma)    # Biblioteca para calculo da norma
library(caret)     # Biblioteca para o calculo de medidas de desempenho do classificador

dados <- read.csv("~/Documentos/disciplinas/reconhecimento/codes/parkinson.csv", header=FALSE)
dados <- dados %>% mutate(id=row_number())

# Semente para reprodução dos resultados
set.seed(368651)

# Inicializando variaveis que armazenaram a acuracia, sensibilidade e especificidade
acu <- c()
sen <- c()
esp <- c()

for (k in 1:100) {
  # Separando o conjunto de dados em treino e teste
  treino <- dados %>% group_by(V23) %>% sample_frac(0.6)
  teste <- anti_join(dados, treino, by="id")
  # Calculando o centroide de cada classe
  c1 <- treino %>% filter(V23 == 0) %>% summarise_all(mean) %>% select(-c("V23","id"))
  c2 <- treino %>% filter(V23 == 1) %>% summarise_all(mean) %>% select(-c("V23","id"))
  ct <- list(as.matrix(c1), as.matrix(c2))
  # Calculando a matriz de covariancia de cada classe
  mat_1 <- treino[,-ncol(treino)] %>% filter(V23 == 0)
  cov_1 <- cov(mat_1[,-ncol(mat_1)])
  mat_2 <- treino[,-ncol(treino)] %>% filter(V23 == 1)
  cov_2 <- cov(mat_2[,-ncol(mat_2)]) 
  covar <- list(as.matrix(cov_1), as.matrix(cov_2))
  # Calculo da matriz de covariancia agregada
  cov_pool <- ((nrow(mat_1)/nrow(treino)) * cov_1) + ((nrow(mat_2)/nrow(treino)) * cov_2)
  # Inicializando as variaveis distancia e classe
  d <- c()
  classe <- c()
  # Calculando as distancias de cada linha do teste para todas as linhas do treino
  for(i in 1:nrow(teste)){
    for(j in 1:2){
      d[j] <- (as.matrix(teste[i,-c(23,24)])-ct[[j]])%*%solve(cov_pool)%*%t(as.matrix(teste[i,-c(23,24)])-ct[[j]]) 
    }
    if (which.min(d) == 1) {
      classe[i] <- 0
    } else {
      classe[i] <- 1
    }
  }
  
  predito <- factor(classe) # Transformando a variavel classe em fator para usar a funcao confusionMatrix
  observado <- factor(teste$V23) # Criando a variavel observado em fator para usar a funcao confusionMatrix
  
  # Armazenando o resultado de cada rodada nas variaveis
  acu[k] <- confusionMatrix(predito, observado, positive = "1")$overall[[1]]
  sen[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[1]]
  esp[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[2]]
  
  cat("Rodada:", k, "\n")
}

##################################################################
##                          RESULTADOS                          ##
##################################################################
media <- mean(acu)
mediana <- median(acu)
min <- min(acu)
max <- max(acu)
desvio <- sd(acu)
media_sense <- mean(sen)
media_espec <- mean(esp)
mediana_sense <- median(sen)
mediana_espec <- median(esp)

# Criando uma tabela com as medidas descritivas
tab <- rbind(media,mediana,min,max,desvio,media_sense,media_espec, mediana_sense, mediana_espec); tab

Classificador Quadrático Gaussiano (Gaussian Quadratic Classifier) usando regularização de Friedman na matriz de covariância

library(tidyverse) # Biblioteca para manipulação de dados
library(pracma)    # Biblioteca para calculo da norma
library(caret)     # Biblioteca para o calculo de medidas de desempenho do classificador

dados <- read.csv("~/Documentos/disciplinas/reconhecimento/codes/parkinson.csv", header=FALSE)
dados <- dados %>% mutate(id=row_number())

# Semente para reprodução dos resultados
set.seed(368651)

# Inicializando variaveis que armazenaram a acuracia, sensibilidade e especificidade
acu <- c()
sen <- c()
esp <- c()

for (k in 1:100) {
  # Separando o conjunto de dados em treino e teste
  treino <- dados %>% group_by(V23) %>% sample_frac(0.6)
  teste <- anti_join(dados, treino, by="id")
  # Calculando o centroide de cada classe
  c1 <- treino %>% filter(V23 == 0) %>% summarise_all(mean) %>% select(-c("V23","id"))
  c2 <- treino %>% filter(V23 == 1) %>% summarise_all(mean) %>% select(-c("V23","id"))
  ct <- list(as.matrix(c1), as.matrix(c2))
  # Calculando a matriz de covariancia de cada classe
  mat_1 <- treino[,-ncol(treino)] %>% filter(V23 == 0)
  cov_1 <- cov(mat_1[,-ncol(mat_1)])
  mat_2 <- treino[,-ncol(treino)] %>% filter(V23 == 1)
  cov_2 <- cov(mat_2[,-ncol(mat_2)]) 
  covar <- list(as.matrix(cov_1), as.matrix(cov_2))
  # Calculo da matriz de covariancia agregada
  cov_pool <- ((nrow(mat_1)/nrow(treino)) * cov_1) + ((nrow(mat_2)/nrow(treino)) * cov_2)
  # Regularização de Friedman
  l <- 0.3
  s_1 <- nrow(mat_1) * cov_1 
  s_2 <- nrow(mat_2) * cov_2 
  cf_1 <- ((1-l)*s_1 + l*nrow(treino)*cov_pool) / ((1-l)*nrow(mat_1) + l*nrow(treino))
  cf_2 <- ((1-l)*s_2 + l*nrow(treino)*cov_pool) / ((1-l)*nrow(mat_2) + l*nrow(treino))
  cf <- list(as.matrix(cf_1), as.matrix(cf_2))
  # Inicializando as variaveis distancia e classe
  d <- c()
  classe <- c()
  # Calculando as distancias de cada linha do teste para todas as linhas do treino
  for(i in 1:nrow(teste)){
    for(j in 1:2){
      d[j] <- (as.matrix(teste[i,-c(23,24)])-ct[[j]])%*%solve(cf[[j]])%*%t(as.matrix(teste[i,-c(23,24)])-ct[[j]]) 
    }
    if (which.min(d) == 1) {
      classe[i] <- 0
    } else {
      classe[i] <- 1
    }
  }
  
  predito <- factor(classe) # Transformando a variavel classe em fator para usar a funcao confusionMatrix
  observado <- factor(teste$V23) # Criando a variavel observado em fator para usar a funcao confusionMatrix
  
  # Armazenando o resultado de cada rodada nas variaveis
  acu[k] <- confusionMatrix(predito, observado, positive = "1")$overall[[1]]
  sen[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[1]]
  esp[k] <- confusionMatrix(predito, observado, positive = "1")$byClass[[2]]
  
  cat("Rodada:", k, "\n")
}

##################################################################
##                          RESULTADOS                          ##
##################################################################
media <- mean(acu)
mediana <- median(acu)
min <- min(acu)
max <- max(acu)
desvio <- sd(acu)
media_sense <- mean(sen)
media_espec <- mean(esp)
mediana_sense <- median(sen)
mediana_espec <- median(esp)

# Criando uma tabela com as medidas descritivas
tab <- rbind(media,mediana,min,max,desvio,media_sense,media_espec, mediana_sense, mediana_espec); tab

Redução de Dimensionalidade

Principal Components Analysis (PCA)

# Importando os dados
dados_source <- read.csv("~/Documentos/disciplinas/reconhecimento/codes/parkinson.csv", header=FALSE)

# Removendo a coluna das classes
dados <- dados_source[,-23]

# Centrando os dados na media
dados <- scale(dados, scale = FALSE)

# Calculando a matriz de covariancia
mat_cov <- cov(dados)

# Calculando os autovalores e autovetores
aux <- eigen(mat_cov)
auto_val <- aux$values
auto_vec <- aux$vectors

# Variancia acumulada de cada autovalor
var_acum <- cumsum(auto_val/sum(auto_val))

# Autovetores referentes aos 2 autovalores que representam 95% da variancia dos dados
V <- auto_vec[,c(1,2)]; V

# Aplicando a transformação nos dados originais
dados_trans <- as.matrix(dados) %*% V

# Adicionando a coluna com as classes para os dados transformados
dados_trans <- data.frame(dados_trans, Classe = factor(dados_source$V23))

# Exportando os dados em formato .txt
write.table(dados_trans, file="parkinson_pca.txt", sep=",", col.names = F, row.names = F)

Discriminante Linear de Fisher

library(tidyverse)
library(MASS)

# Importando e limpando o dataset
dados <- read.csv("~/Documentos/disciplinas/reconhecimento/codes/parkinson.csv", header=FALSE)

# Coluna com a classe dos dados
classe <- dados[,23]; classe

# Removendo a coluna das classes
dados <- dados[,-23]

# Centrando os dados na media
dados <- scale(dados, center = TRUE, scale = FALSE)
dados <- data.frame(dados, classe)

# Calculando os centroides por classe e geral
cl.centroides <- dados %>% group_by(classe) %>% summarise_all(mean)
cl.centroides <- cl.centroides[,-1]

gl.centroides <- dados %>% summarise_all(mean) %>% as_tibble()
gl.centroides <- gl.centroides[,-23]

# Calculando as matrizes de covariancia de cada class
dados.cl0 <- dados %>% filter(classe==0)
mtcov.cl0 <- cov(dados.cl0[,-23])

dados.cl1 <- dados %>% filter(classe==1)
mtcov.cl1 <- cov(dados.cl1[,-23])

# Matriz de dispersão intraclasses
SW <- dim(dados.cl0)[1]*mtcov.cl0 + dim(dados.cl1)[1]*mtcov.cl1

# Matriz de dispersão interclasses
cl.0 <- as.matrix(cl.centroides[1,] - gl.centroides)
aux1 <- t(cl.0) %*% cl.0
cl.1 <- as.matrix(cl.centroides[2,] - gl.centroides)
aux2 <- t(cl.1) %*% cl.1

SB <- aux1 + aux2

# Auto-valores e Auto-vetores
aux3 <- eigen((solve(SW)%*%SB)); aux3
eigen.val <- round(Re(aux3$values),10)
eigen.vec <- Re(aux3$vectors)

# Matriz com os autovetores correspondentes a maior autovalor
Q <- matrix(eigen.vec[,1],nrow=length(eigen.vec[,1]),byrow=F)

# Dados sem a coluna classe
D <- dados[,-23]

# Dados transformados
X1 <- as.matrix(D) %*% Q 
dados_trans <- data.frame(TD, classe)

# Exportando os dados em formato .txt
write.table(dados_trans, file="parkinson_lda.txt", sep=",", col.names = F, row.names = F)

Atividade Computacional 2

Questão Única - Tópico: Quantização vetorial para redução de grandes volumes de dados em problemas de classificação. Acesse através do link abaixo o conjunto de dados para uso neste trabalho.

http://archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients

Pede-se:

  1. Compare o desempenho dos classificadores Vizinho Mais Próximo(NN), Distância Mínima ao Centróide(DMC) e Classificador Quadráticos Guassiano(CQG) antes e depois da redução de volume. Preencha a tabela de resultado abaixo. Número de rodadas indepentendes de treino/teste: 100.
Classificador Média Mediana Mínimo Máximo Desvio Padrão Sensibilidade Especificidade
DMC 0.536 0.536 0.525 0.548 0.004 0.671 0.498
NN 0.695 0.695 0.686 0.704 0.003 0.299 0.808
CQG 0.645 0.644 0.628 0.668 0.008 0.713 0.626
DMC+Redução 0.589 0.589 0.550 0.634 0.015 0.691 0.487
NN+Redução 0.309 0.311 0.280 0.345 0.014 0.284 0.334
CQG+Redução 0.639 0.639 0.600 0.678 0.014 0.949 0.329

K-médias

df <- read.csv("C:/Users/fabio/Documents/disciplinas/reconhecimento/datasets/credits.csv", header=FALSE)
X <- as.matrix(df)

K <- 1000
dot <- c()
cluster <- c()

prevcentroides <- matrix(0, K, dim(X)[2])

set.seed(2)
centroides <- X[sample(1:dim(X)[1], K), ]
while(!isTRUE(all.equal(centroides, prevcentroides))){
  for(i in 1:dim(X)[1]){
    for(j in 1:dim(centroides)[1]){
      dot[j] = (X[i, ] - centroides[j, ]) %*% (X[i, ] - centroides[j, ])
    }
    cluster[i] = which.min(dot)
  }
  
  prevcentroides <-  centroides
  
  for(k in 1:K){
    centroides[k,] <- colMeans(X[which(cluster==k),])
  }
}

cluster; table(cluster)
  1. Qual dos classificadores se beneficiou mais da redução de volume?

A redução não beneficiou nenhum dos classificadores implementados. Porém se tomarmos como medida de qualidade do classificador a sensibilidade, podemos afirmar que o classificador quadrático gaussiano apresentou um aumento significativo em sua sensibilidade. Ou seja, o quanto ele identifica os casos que realmente positivos.

Atividade Computacional 3

Questão Única - Tópico: Clusterização de dados via algoritmo K-médias. Usando o conjunto de dados disponibilizado no SIGAA, pede-se:

  1. Estimar o número de grupamentos usando os índices de validação de Dunn e Calinski-Harabasz. Houve divergência entre os resultados sugeridos pelos índices? Em caso afirmativo, o que justifica tal divergência?

Os índices não concordaram quanto a quantidade clusters. O índice de Dunn apresentou seu maior valor para um número de grupos igual a 5. Já o índice de Calinski-Harabasz apresentou seu máximo para um número de clusters igual a 7. Uma possível explicação para essa divergência é como os dois índices são calculados. O de Dunn baseia-se em medidas de distância intra e entre cluster. Já o índice de Calinski é calculado sobre os erros quadráticos intra e entre clusters. Além disso, existe uma constate na medida de Calinski-Harabasz, \(\frac{N-k}{k-1}\), que depende da quantidade de cluster e do total de pontos no conjunto de dados.

Abaixo os gráficos da média dos índices para valores de \(2\leq K \leq 20\) em 1000 rodadas do algoritmo Kmeans.

figura 04
  1. Usando o menor dos valores para o número de agrupamentos do item anterior, realizar a análise estatística de cada agrupamento encontrado. Forneça a posição de cada protótipo, além dos valores mínimo, máximo, mediana e desvio-padrão de cada atributo por agrupamento.
RESUMO DESCRITIVO POR GRUPO
RESUMO DESCRITIVO POR GRUPO
Var1 Var2 Var3 Var4 Var5 Var6
Grupo 1 - Tamanho: 156
Média 99.624 6.086 1927.779 1.984 2.077 792089.532
Mediana 100.000 5.000 458.349 1.809 1.809 820575.500
Desvio 2.877 3.823 4985.980 1.018 0.990 118995.656
Min 66.667 2.000 47.310 0.286 0.303 601002.000
Max 100.000 20.000 37082.735 3.464 3.464 976193.000
Grupo 2 - Tamanho: 40
Média 98.750 3.607 393.655 3.036 3.045 8000882.450
Mediana 100.000 2.583 154.190 3.464 3.464 8000845.500
Desvio 7.906 3.046 458.257 0.759 0.747 548.022
Min 50.000 2.000 77.509 0.615 0.615 8000011.000
Max 100.000 17.000 2020.637 3.464 3.464 8001856.000
Grupo 3 - Tamanho: 276
Média 99.874 4.215 1174.987 2.334 2.384 9581536.612
Mediana 100.000 3.000 500.353 2.335 2.335 9520701.500
Desvio 1.145 3.912 1943.558 1.087 1.056 99669.421
Min 86.667 1.667 45.340 0.384 0.425 9464070.000
Max 100.000 37.000 14234.424 3.464 3.464 9995020.000
Grupo 4 - Tamanho: 655
Média 98.385 3.907 1908.928 2.111 2.184 122928.412
Mediana 100.000 3.000 332.320 1.954 2.161 130085.000
Desvio 8.682 4.545 6924.837 1.056 1.019 65267.733
Min 0.000 0.000 38.220 0.208 0.271 10.000
Max 100.000 72.667 117287.299 3.464 3.464 400010.000
Grupo 5 - Tamanho: 574
Média 99.563 4.066 972.518 2.140 2.184 9338973.735
Mediana 100.000 4.000 310.932 1.809 1.954 9356032.500
Desvio 3.029 1.787 2004.944 0.997 0.976 63326.508
Min 66.667 0.000 67.612 0.385 0.564 9100027.000
Max 100.000 14.600 24965.861 3.464 3.464 9440039.000
Note:
As linhas em azul são a posição de cada protótipo.
Link para download dos dados clusterizados