0
\$\begingroup\$

I have written this k-means algorithm without using any class structure. The audience of my code are students who are pretty new to Python. Is it possible to review the code so that it is more readable by beginner of Python, and at the same time efficient. I wrote the code quite quickly, without reviewing it properly. I have a nagging feeling that it looks more like a code spaghetti. So I need some pointers here, please.

import matplotlib.pyplot as plt
import numpy as np

def colorCluster(data, k , numPoints,  clusterColors, numIterations):
    #Get the distance from the centroids
    def getDistFromCentroid(data,centroids,k):
        def getDistance(a, X):
            a = a.T
            X = X.T
            len = X.shape[0]
            distance = np.zeros(len)
            for i in range (len):
                b = X[i]
                distance[i] = np.sqrt(np.square(a[0] - b[0]) + np.square(a[1] - b[1]))
            return distance

        dist = np.zeros((k,numPoints))
        for i in range(k):
            dist[i] = getDistance(centroids[i], data)
        return dist

    #Get the indices of the k clusters
    def getIndicesOfClusters(dist):
        indArr = []
        for i in range(k):
            ind = []
            for j in range(numPoints):
                if(np.argmin(dist[:,j]) == i):
                    ind.append(j)
            indArr.append(ind)
        return indArr
    

    #Using the indices of the clustered points
    #draw on the canvas
    def drawClusterPoints(dist):
        def plotMat(mat , ind, color):
            ind = np.array(ind).reshape(-1,1).T
            p = mat[:,ind]
            plt.plot(p[0], p[1], 'o', color = color)

        indArr = getIndicesOfClusters(dist)
        for i in range(k):
            plotMat(data, indArr[i], clusterColors[i])
        
    #Centroids are calcuated using the average 
    #of x and y coordinates in each cluster
    def getCentroid(dist):
        indArr = getIndicesOfClusters(dist)
        centroids = []
        for i in range(k):
            centroids.append(np.average(data[:,indArr[i]], axis = 1))
        return np.array(centroids)

    #Update the whole code
    #Find new centroids 
    #Calculate the new distances from centroids
    #Repeat for numIterations
    def connectAll():
        centroids = np.random.randint(1,numPoints, size = [k,2])
        for i in range(numIterations):
            dist = getDistFromCentroid(data,centroids,k)
            centroids = getCentroid(dist)
            drawClusterPoints(dist)
            #plt.show()
            plt.draw()
            plt.pause(0.00000000000001)
            plt.clf()
            #print(centroids.shape)
    connectAll()

def kmeans():
    #initialize
    numPoints = 1000
    data = np.random.randint(1,numPoints, size = (2,numPoints))
    plt.plot(data[0], data[1], 'o', color = "black")
    plt.show()
    k = 9
    numIterations = 10
    clusterColors = ["red","brown", "black", "blue", "orange", "purple", "olive", "gray", "cyan"]
    colorCluster(data, k , numPoints,  clusterColors, numIterations)

```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.