# How to interpret the meaning of KMeans clusters

Using the elbow method, I determine the correct number of clusters for the KMeans function. Having done that, I still have no idea how to interpret the clusters in a meaningful way. If someone asked me what any of the clusters represent, I have no idea how to answer that. Is there a way to use the results of KMeans to assign some sort of meaningful label to the clusters?

• Why wouldn't the mean of each cluster be the natural label to use for this method? – whuber May 19 at 20:06
• Each cluster is supposed to be a set of values that are reasonably well approximated by the cluster center (their mean). Thus, the center can serve as a surrogate for each of the values in it. You would interpret that center in the same way you would interpret any individual value. – whuber May 19 at 20:18
• Sorry, I'm having trouble posting responses because I am new at this. So, to restate my question more precisely, the only think KMeans returns are the cluster centers. For example, given two clusters formed from five variables, the cluster centers are: array([[0.57197373, 0.41186226, 0.56913828, 0.42642165, 0.43697047], [0.25754168, 0.29362709, 0.25140866, 0.14460985, 0.38022388]]) How can these by used to interpret the clusters? – Stephen O'Brien May 19 at 20:20
• 1) There is no such thing as a well defined elbow method. 2) What is your aim of clustering? What are you interested in? Without having questions to the data in mind you won't get answers. 3) The clusters assign every observation to the closest cluster center, so you can look at the cluster centers, which tell you the location of the clusters. Obviously you need to be able to interpret values on your own variables. – Lewian May 19 at 22:27

Clustering is descriptive: a central point in each cluster serves as a surrogate, or approximate descriptor of, the points in the cluster. Use the coordinates of these central points for labels.

As an idea for consideration--certainly not as the only or even the best approach--you could assess how far each central coordinate is from a center of all the data. Do this on a relative basis, as with a z score. Characterize the coordinates according to whether they are smaller or larger than average. Maybe modify those characterizations according to how far from average they are.

Here is an example using the four-dimensional "Iris" dataset of 150 observations with two k-means clusters. First, the cluster centers (heavily rounded):

    Sepal Length   Sepal Width   Petal Length   Petal Width
1              6             3              5           2.0
2              5             3              2           0.3


Next, their (rounded) Z-scores. These are defined, as usual, as the difference between a coordinate and the dataset mean for that coordinate, all divided by the standard deviation in the dataset:

    Sepal Length   Sepal Width   Petal Length   Petal Width
1            0.6          -0.4            0.7           0.7
2           -1.0           0.7           -1.0          -1.0


Using (arbitrarily) a rounded threshold of $$1$$ to intensify the characterizations of "high" or "low" values produces this summary:

Cluster   Sepal Length   Sepal Width   Petal Length   Petal Width
1           High           ---           High          High
2       Very Low          High       Very Low      Very Low


The "labels" are the lines--but now each line is highly interpretable in a qualitative sense. Cluster 1 consists of observations with relatively high sepal lengths and petal sizes. Cluster 2 consists of observations with extremely low sepal lengths and petal sizes (and, incidentally, somewhat high sepal widths). Thus, going just a little further, we might say the clusters are distinguished by sepal shape and petal size.

This is the R code that produced these results, automatically. Apart from the initial data-input block, it generalizes to any numerical array of data like iris. It was written in a relatively straightforward manner to assist porting it to other platforms.

#
# Data.
#
data(iris)
iris <- iris[, -5]
colnames(iris) <- paste(" ", gsub("[.]", " ", colnames(iris)))
#
# K-means.
#
x <- kmeans(iris, 2)
#
# Automatic label assignment.
#
threshold <- 1                 # Adjust as desired.
s <- apply(iris, 2, sd)        # Column standard deviations
m <- colMeans(iris)            # Column means
z <- t((t(x$$centers) - m) / s) # Z-scores of the centers pos <- sapply(round(z), function(u) switch(2+sign(u), "Low", "---", "High")) mod <- ifelse(abs(z) >= threshold, "Very ", "") # Intensifiers labels <- paste0(mod, pos) # # Output. signif rounds its first argument to the given number of decimals. # print(signif(x$$centers, 1))
print(signif(z, 1))
print(array(labels, dim(z), list(Cluster=rownames(z), colnames(z))),
quote=FALSE, right=TRUE)


In a word: No. You'll need to go through the cluster by hand and try to spot patterns.