How to scatter plot a dict of lists containing arrays in Matplotlib? (Screenshot in details)
Question: What I want to do is plotting data in a _dict_ , preferably using Matplotlib.
Below is a screenshot since I think looking at the data structure makes it
easier to understand. But here is also a description.

  * A _dict_ contains 7 _lists_. 
  * Each _list_ represents a cluster.
  * Each _list_ contains a number of _arrays_ with two items in it. 
  * Each _array_ represents a two-dimensional point.

I want to recreate the results in this Blog post. Unfortunately the author
didn't provide the code he used for the plots.
<https://datasciencelab.wordpress.com/2013/12/12/clustering-with-k-means-in-
python/>

Here is the screenshot:

[![enter image description
here](http://i.stack.imgur.com/eONjG.png)](http://i.stack.imgur.com/eONjG.png)

In case it helps, here is the full code I used to generate the clusters:

    
    
    import numpy as np
    import random
    import matplotlib.pyplot as plt # STACKOVERFLOW
    
    # k-Means Algorithm (Lloyd's Algorithm) 
    def cluster_points(X, mu):
        clusters  = {}
        for x in X:
            bestmukey = min([(i[0], np.linalg.norm(x-mu[i[0]])) \
                        for i in enumerate(mu)], key=lambda t:t[1])[0]
            try:
                clusters[bestmukey].append(x)
            except KeyError:
                clusters[bestmukey] = [x]
        return clusters
    
    def reevaluate_centers(mu, clusters):
        newmu = []
        keys = sorted(clusters.keys())
        for k in keys:
            newmu.append(np.mean(clusters[k], axis = 0))
        return newmu
    
    def has_converged(mu, oldmu):
        return set([tuple(a) for a in mu]) == set([tuple(a) for a in oldmu])
    
    def find_centers(X, K):
        # Initialize to K random centers
        oldmu = random.sample(X, K)
        mu = random.sample(X, K)
        while not has_converged(mu, oldmu):
            oldmu = mu
            # Assign all points in X to clusters
            clusters = cluster_points(X, mu)
            # Reevaluate centers
            mu = reevaluate_centers(oldmu, clusters)
        return(mu, clusters)
    
    
    # initialization
    def init_board_gauss(N, k):
        n = float(N)/k
        X = []
        for i in range(k):
            c = (random.uniform(-1, 1), random.uniform(-1, 1))
            s = random.uniform(0.05,0.5)
            x = []
            while len(x) < n:
                a, b = np.array([np.random.normal(c[0], s), np.random.normal(c[1], s)])
                # Continue drawing points from the distribution in the range [-1,1]
                if abs(a) < 1 and abs(b) < 1:
                    x.append([a,b])
            X.extend(x)
        X = np.array(X)[:N]
        return X
    
    X = init_board_gauss(200,3)
    
    # generating clusters
    mu, clusters = find_centers(X, 7)
    clusters = cluster_points(X, mu)
    


Answer: I came up with a solution. [![enter image description
here](http://i.stack.imgur.com/lugVE.png)](http://i.stack.imgur.com/lugVE.png)

Here is what I changed/added to the code:

    
    
    # Initialize points
    n_points = 200
    n_clusters = 7
    X = init_board_gauss(n_points, n_clusters)
    
    # Cluster points
    mu, clusters = find_centers(X, n_clusters)
    clusters = cluster_points(X, mu)
    
    # Generate random colors
    def generate_random_color():
        r = lambda: random.randint(0,255)
        return '#%02X%02X%02X' % (r(),r(),r())
    
    # Plot each cluster
    for i in range(0, n_clusters):
        colx = tuple(x[0] for x in clusters[i])
        coly = tuple(x[1] for x in clusters[i])
        cluster_color = generate_random_color()
        plt.scatter(colx,coly, color=cluster_color)
    

And here is the full code:

    
    
    import matplotlib.pyplot as plt
    import numpy as np
    import random
    
    # k-Means Algorithm (Lloyd's Algorithm) 
    def cluster_points(X, mu):
        clusters  = {}
        for x in X:
            bestmukey = min([(i[0], np.linalg.norm(x-mu[i[0]])) \
                        for i in enumerate(mu)], key=lambda t:t[1])[0]
            try:
                clusters[bestmukey].append(x)
            except KeyError:
                clusters[bestmukey] = [x]
        return clusters
    
    def reevaluate_centers(mu, clusters):
        newmu = []
        keys = sorted(clusters.keys())
        for k in keys:
            newmu.append(np.mean(clusters[k], axis = 0))
        return newmu
    
    def has_converged(mu, oldmu):
        return set([tuple(a) for a in mu]) == set([tuple(a) for a in oldmu])
    
    def find_centers(X, K):
        # Initialize to K random centers
        oldmu = random.sample(X, K)
        mu = random.sample(X, K)
        while not has_converged(mu, oldmu):
            oldmu = mu
            # Assign all points in X to clusters
            clusters = cluster_points(X, mu)
            # Reevaluate centers
            mu = reevaluate_centers(oldmu, clusters)
        return(mu, clusters)
    
    
    # Initialization
    def init_board(N):
        X = np.array([(random.uniform(-1, 1), random.uniform(-1, 1)) for i in range(N)])
        return X    
    
    def init_board_gauss(N, k):
        n = float(N)/k
        X = []
        for i in range(k):
            c = (random.uniform(-1, 1), random.uniform(-1, 1))
            s = random.uniform(0.05,0.5)
            x = []
            while len(x) < n:
                a, b = np.array([np.random.normal(c[0], s), np.random.normal(c[1], s)])
                # Continue drawing points from the distribution in the range [-1,1]
                if abs(a) < 1 and abs(b) < 1:
                    x.append([a,b])
            X.extend(x)
        X = np.array(X)[:N]
        return X
    
    
    # Initialize points
    n_points = 200
    n_clusters = 7
    X = init_board_gauss(n_points, n_clusters)
    
    # Cluster points
    mu, clusters = find_centers(X, n_clusters)
    clusters = cluster_points(X, mu)
    
    # Generate random colors
    def generate_random_color():
        r = lambda: random.randint(0,255)
        return '#%02X%02X%02X' % (r(),r(),r())
    
    # Plot each cluster
    for i in range(0, n_clusters):
        colx = tuple(x[0] for x in clusters[i])
        coly = tuple(x[1] for x in clusters[i])
        cluster_color = generate_random_color()
        plt.scatter(colx,coly, color=cluster_color)
    

