## Esercizio di cluster analysis ## Distanze tra le imprese sulla base della Tab. 8.7 Tab8.7 <- read.table("Tab8.7.txt", sep="\t", h=T, dec=".") dimnames(Tab8.7)[[1]] <- c("Alfa", paste("U",2:6, sep="")) ## Riproduciamo la Tabella 8.9: distanza euclidea al quadrato (D2) round(dist(Tab8.7[,-1])^2, 2) ## Standard: distanza euclidea (senza quadrati) round(dist(Tab8.7[,-1]), 2) ## Alt.: distanza "city block", o di Manhattan round(dist(Tab8.7[,-1], method="manhattan"), 2) ## Clustering basato sulla distanza: mydist.D2 <- dist(Tab8.7[,-1])^2 mydist.CB <- dist(Tab8.7[,-1], method="manhattan") ## (NB usiamo il metodo di Ward per calcolare la distanza tra ## individui e gruppi e tra cppie di gruppi) res.hc.D2 <- hclust(mydist.D2, method = "ward.D2") plot(res.hc.D2) ## screeplot fatto in casa plot(res.hc$height, length(res.hc$height):1, type="l") points(res.hc$height, length(res.hc$height):1, pch=19) ## la distanza di raggruppamento (che per noi è un "male") cresce ## vistosamente nel passaggio da 3 gruppi a 2: ## il nostro risultato "preferito" è: (Alfa, U3); U2; (U4, U5, U6) ##################### ## Esercizio di raggruppamento "a mano", secondo quanto illustrato ## nella tabella 8.10 (NB usiamo un criterio diverso: centroide vs. ## legame completo) ## per semplicità: dati1 <- Tab8.7[, -1] ## scegliamo: ## - la distanza euclidea come funzione di distanza ## - il metodo dei centroidi come criterio di distanza ## tra gruppi ## prepariamo un vettore per le distanze di unione dei cinque passi: udist <- rep(NA, 5) ## primo passo: ## calcoliamo la matrice di distanza tra le unità round(dist(dati1), 2) ## raggruppiamo U5, U6 nel gruppo G1 dati2 <- rbind(dati1[1:4, ], apply(dati1[5:6, ], 2, mean)) dimnames(dati2)[[1]][5] <- "G1" ## la distanza di unione è la minima distanza; qui è tra U5 e U6: udist[1] <- min(dist(dati1)) ## secondo passo: round(dist(dati2), 2) ## ora G1 con U4 dati3 <- rbind(dati2[1:3, ], apply(dati2[4:5, ], 2, mean)) dimnames(dati3)[[1]][4] <- "G2" udist[2] <- min(dist(dati2)) ## terzo passo: round(dist(dati3), 2) ## ora Alfa con U3 dati4 <- rbind(apply(dati3[c(1,3), ], 2, mean), dati3[c(2,4), ]) dimnames(dati4)[[1]][1] <- "G3" udist[3] <- min(dist(dati3)) ## quarto passo: round(dist(dati4), 2) udist[4] <- min(dist(dati4)) ## U2 con G2, poi l'ultimo raggruppamento è obbligato. ## calcoliamo la distanza di unione lo stesso, ci serve per lo ## screeplot dati5 <- rbind(dati4[1, , drop=FALSE], apply(dati4[2:3, ], 2, mean)) dimnames(dati5)[[1]][2] <- "G4" udist[5] <- min(dist(dati5)) ## screeplot: plot(udist[5:1], 1:5, type="l", ylab="Gruppi", xlab="Distanza di unione") # nota l'inversione dell'asse y points(udist[5:1], 1:5, pch=19) # solo per leggibilità ## la conclusione è sempre di preferire la divisione in 3 gruppi ################################################## ## Visualizzazione un po' più "fancy": library(factoextra) ## questo package contiene una funzione alternativa che può ## calcolare (anche) le stesse distanze di 'dist()' get_dist(Tab8.7[,-1]) mydist <- get_dist(Tab8.7[,-1]) fviz_dist(mydist, order = TRUE, show_labels = TRUE, lab_size = NULL, gradient = list(low = "red", mid = "white", high = "blue")) #fviz_dend(res.hc, cex = 0.5, k = 4, palette = "jco")