# Cluster quality internal validity after PCA

I've been trying to calculate internal validity for clusters after PCA using the iris example, but I couldn't.

So far I have this:

data(iris)
library(factoextra)
iris.scaled <- scale(iris[, -5])
# k-means group number of each observation
km.res <- eclust(iris.scaled, "kmeans", k = 3, nstart = 2, graph = FALSE)
km.res$cluster # Visualize k-means clusters fviz_cluster(km.res, geom = "point", frame.type = "norm") # Compute pairwise-distance matrix dd <- dist(iris.scaled, method ="euclidean") # Statistics for k-means clustering km_stats <- cluster.stats(dd, km.res$cluster)
km_stats

And I get the following result:

$clus.avg.silwidths 1 2 3 0.6363162 0.3473922 0.3933772$avg.silwidth
[1] 0.4599482

In order to try to use cluster.stats after PCA I run this:

library(FactoMineR)
library(factoextra)
library(fpc)

iris.pca <- PCA(iris.scaled, graph = FALSE)
iris.hc <- HCPC(iris.pca)

#Here are the individuals and the dimensions
iris.pca$$ind$$contrib

#here are the clusters
iris.hc$data.clust[,5] dis <- dist(iris.pca$$ind$$contrib, method ="euclidean") #I need clusters to be numeric p<- as.numeric(iris.hc$data.clust[,5])

km_stats <- cluster.stats(dis, p)
km_stats

But I get this result:

$clus.avg.silwidths 1 2 3 0.39043588 -0.01734689 -0.15697508$avg.silwidth
[1] 0.07483054
• Do you have a specific question? What is wrong with these results? – OTStats Aug 7 '19 at 13:56
• The result is wrong, the silhouette of the clusters after PCA should be higher, in one of the answers I got (in the link at the begining of my question) I was told that silhouette was higher after PCA using the iris dataset.. and it makes sense, clusters at least "look" better after PCA – Ana Aug 7 '19 at 14:15

You didn't run k-means on the output of PCA.

PCA substantially changes the weights of features. It distorts the data heavily. Also, $ind$contrib sounds wrong to me. You don't want to project to contributions.

Hence, a result computed on the original data, but evaluated after PCA is expected to score quite badly.

I think this one works:

distanc <- dist(iris.pca$$ind$$coord[,1:2], method="euclidean" ) #distances of the first two components
iris.hc$$data.clust[,5] #here are the clusters clusters<- as.numeric(iris.hc$$data.clust[,5])
km_stats <- cluster.stats(distanc, clusters)
km_stats

Now I have:

$clus.avg.silwidths 1 2 3 0.6540650 0.4418605 0.4309233$avg.silwidth
[1] 0.509168

I'm using the coords of the individuals, is this ok?