2
$\begingroup$

I have done clustering using Kmeans using sklearn. While it has a method to print the centroids, I am finding it rather bizarre that scikit-learn doesn't have a method to find out the cluster diameter (or that I have not seen it so far). Is there a neat way to obtain this for each cluster together with points associated with a cluster?

I currently have this rather kludgy code to do it

import numpy as np
from sklearn.cluster import KMeans
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target

estimator = KMeans(n_clusters=3)
estimator.fit(X)
print({i: np.where(estimator.labels_ == i)[0] for i in range(estimator.n_clusters)}) #get the indices of points for each cluster
$\endgroup$
1
  • $\begingroup$ What do you mean here by "length" of a cluster? diameter? number of points? $\endgroup$
    – Sean Owen
    Jun 6, 2018 at 20:35

1 Answer 1

5
$\begingroup$

For the time being, I've prepared a workaround solution:

#iris example
iris = datasets.load_iris()
x = iris.data
y = iris.target


estimator = KMeans(n_clusters=3)
y_kmeans = estimator.fit_predict(x)

To get the clusters' radii you can use the following code snippet:

#empty dictionaries

clusters_centroids=dict()
clusters_radii= dict()

'''looping over clusters and calculate Euclidian distance of 
each point within that cluster from its centroid and 
pick the maximum which is the radius of that cluster'''

for cluster in list(set(y)):

    clusters_centroids[cluster]=list(zip(estimator.cluster_centers_[:, 0],estimator.cluster_centers_[:,1]))[cluster]
    clusters_radii[cluster] = max([np.linalg.norm(np.subtract(i,clusters_centroids[cluster])) for i in zip(x[y_kmeans == cluster, 0],x[y_kmeans == cluster, 1])])

It will give you this: enter image description here

Please note K-means:

  • Implicitly assumes all clusters have the same radius
  • Separates the data into Voronoi-cells (which can be seen from here as well).
  • Cluster points (circles) can overlap (it is how it is defined).

If you want to relax the shape of the clusters (not strictly spherical or circles like K-means), you should perform Gaussian mixture models.

Appendix (To Reproduce the above Visualization):

#Visualising the clusters and cluster circles

fig, ax = plt.subplots(1,figsize=(7,5))

plt.scatter(x[y_kmeans == 0, 0], x[y_kmeans == 0, 1], s = 100, c = 'red', label = 'Iris-setosa')
art = mpatches.Circle(clusters_centroids[0],clusters_radii[0], edgecolor='r',fill=False)
ax.add_patch(art)

plt.scatter(x[y_kmeans == 1, 0], x[y_kmeans == 1, 1], s = 100, c = 'blue', label = 'Iris-versicolour')
art = mpatches.Circle(clusters_centroids[1],clusters_radii[1], edgecolor='b',fill=False)
ax.add_patch(art)

plt.scatter(x[y_kmeans == 2, 0], x[y_kmeans == 2, 1], s = 100, c = 'green', label = 'Iris-virginica')
art = mpatches.Circle(clusters_centroids[2],clusters_radii[2], edgecolor='g',fill=False)
ax.add_patch(art)

#Plotting the centroids of the clusters
plt.scatter(estimator.cluster_centers_[:, 0], estimator.cluster_centers_[:,1], s = 100, c = 'yellow', label = 'Centroids')

plt.legend()
plt.tight_layout()
plt.savefig('kmeans.jpg',dpi=300)
$\endgroup$
9
  • $\begingroup$ length means number of points associated .Actually I have to find the cluster with one point and take euclidean distance of that point to every other point in all cluster so that the points with minimum distance will be added to cluster of length one $\endgroup$ Jun 7, 2018 at 9:11
  • $\begingroup$ First: "number of points associated" is the "number of points associated", still it is not clear why you keep calling it length!!? Also what you said in the the remaining is not clear as well. "to find the cluster with one point", why? It sounds you are trying to change the way kmeans find clusters and force it to do something else. Good luck anyway! $\endgroup$ Jun 7, 2018 at 9:34
  • $\begingroup$ So can you help me to get number of point associated with each cluster? Reason of choosing a cluster with one point is necessary for my algorithm $\endgroup$ Jun 7, 2018 at 9:46
  • 1
    $\begingroup$ What do you mean you get the expected results but not the plot? What is the error? Where do you plot it? $\endgroup$ Feb 24, 2020 at 6:50
  • 1
    $\begingroup$ Sure. That should happen, it is basic column allocations in pandas. Once you read it df = pandas.read_csv('yourfile'), then you do x = df [['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm']] y = df['Species'] Then the rest should work. I cannot be more helpful than this. You have to google how to work with pandas, features. $\endgroup$ Oct 30, 2020 at 16:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.