層次聚類分析
在層次聚類中,起初每一個實例或觀測值屬於一類。聚類就是每一次把兩類聚成新的一類,直到所有的類聚成單個類為止,算法如下:
(1) 定義每個觀測值(行或單元)為一類;
(2) 計算每類和其他各類的距離;
(3) 把距離最短的兩類合並成一類,這樣類的個數就減少一個;
(4) 重復步驟(2)和步驟(3),直到包含所有觀測值的類合並成單個的類為止。
層次聚類方法
單聯動聚類方法傾向於發現細長的、雪茄型的類。它也通常展示一種鏈式的現象,即不相似的觀測值分到一類中,因為它們和它們的中間值很相像。全聯動聚類傾向於發現大致相等的直徑緊湊類。它對異常值很敏感。平均聯動提供了以上兩種方法的折中。相對來說,它不像鏈式,而且對異常值沒有那么敏感。它傾向於把方差小的類聚合。
Ward法傾向於把有少量觀測值的類聚合到一起,並且傾向於產生與觀測值個數大致相等的類。它對異常值也是敏感的。質心法是一種很受歡迎的方法,因為其中類距離的定義比較簡單、易於理解。
層次聚類方法可以用hclust()函數來實現,格式是hclust(d, method=),其中d是通過dist()函數產生的距離矩陣,並且方法包括 "single"、"complete"、"average"、"centroid"和"ward"。
(1)營養數據的平均聯動聚類:
data(nutrient, package="flexclust")
row.names(nutrient) <- tolower(row.names(nutrient)) #將行名改為小寫(個人習慣)
nutrient.scaled <- scale(nutrient) #標准化為均值為0、方差為1
d <- dist(nutrient.scaled) #27種食物之間的距離采用歐幾里得距離,默認為歐幾里得距離
fit.average <- hclust(d, method="average") # hclust()做層次聚類,應用的方法是平均聯動
plot(fit.average, hang=-1, cex=.8, main="Average Linkage Clustering")
#plot()函數中的hang命令展示觀測值的標簽(讓它們在掛在0下面)
結果分析:樹狀圖應該從下往上讀,它展示了這些條目如何被結合成類。每個觀測值起初自成一類,然后相距最近的兩類(beef braised和smoked ham)合並。其次,pork roast和pork simmered合並,chicken canned和tuna canned合並。再次,beef braised/smoked ham這一類和pork roast/pork simmered這一類合並(這個類目前包含四種食品)。合並繼續進行下去,直到所有的觀測值合並成一類。高度刻度代表了該高度類之間合並的判定值。對於平均聯動來說,標准是一類中的點和其他類中的點的距離平均值。
NbClust包提供了眾多的指數來確定在一個聚類分析里類的最佳數目。不能保證這些指標得出的結果都一致。事實上,它們可能不一樣。但是結果可用來作為選擇聚類個數K值的一個參考。NbClust()函數的輸入包括需要做聚類的矩陣或是數據框,使用的距離測度和聚類方法,並考慮最小和最大聚類的個數來進行聚類。它返回每一個聚類指數,同時輸出建議聚類的最佳數目。下面的代碼清單使用該方法處理營養數據的平均聯動聚類。
(2)選擇聚類的個數
install.packages("NbClust")
library(NbClust)
devAskNewPage(ask=TRUE)
nc <- NbClust(nutrient.scaled, distance="euclidean", min.nc=2, max.nc=15, method="average")
table(nc$Best.n[1,]) #看分組的支持數
結果分析:這里,四個評判准則贊同聚類個數為2,四個判定准則贊同聚類個數為3,等等。
barplot(table(nc$Best.n[1,])) #畫圖
結果分析:橫坐標是分組數,縱坐標是支持數,(舉例:建議分成2組的,有4個支持),可以試着用“投票”個數最多的聚類個數(2、3、5和15)並選擇其中一個使得解釋最有
意義。下面的代碼清單展示了五類聚類的方案。
clusters<-cutree(fit.average,k=5) #分成5組
table(clusters) #分配情況
結果分析:第一類有7個觀測值,第二類有16個觀測值,等等。
aggregate(nutrient,by=list(cluster=clusters),median) #原始度量
#描述聚類,aggregate()函數用來獲取每類的中位數
結果分析:總共是5類,每一類都有一個明顯的特征,可以看數值的大小
aggregate(as.data.frame(nutrient.scaled), by=list(cluster=clusters), median) #標准度量
plot(fit.average, hang=-1, cex=.8,
main="Average Linkage Clustering\n5 Cluster Solution") #顯示繪圖結果
rect.hclust(fit.average, k=5) #rect.hclust()函數用來疊加五類的解決方案
結果分析:sardines canned形成自己的類,因為鈣比其他食物組要高得多。beef heart也是單獨成類,是因為富含蛋白質和鐵。clams類是低蛋白和高鐵的。從beef roast到pork simmered的類中,所有項目都是高能量和高脂肪的。最后,最大的類(從mackerel canned到bluefish baked)含有相對較低的鐵。