0
$\begingroup$

I wrote some Python code that uses the output from a principal component analysis to perform k-means on. The output to my script below is

Cluster 1: Data Points: [[ 1.87192346 -1.12568277] [ 1.97012514 -0.70532312] [ 3.45778709 -0.64678024] [ 2.61029111 -2.32216733]] Center: [ 2.4775317 -1.19998837]

Cluster 2: Data Points: [[-3.22914198 0.47263998] [-2.21336465 -0.30760444] [-2.46006546 -0.30036711] [-1.39971878 -0.56487664] [-2.68357487 -0.4820239 ] [-1.75873004 -0.12933835] [-1.20901232 -0.97706353] [-1.4371756 0.58947658]] Center: [-2.04884796 -0.21239468]

Cluster 3: Data Points: [[ 0.84583072 0.10252569] [ 0.17431096 0.05538357] [ 0.85267424 -0.37199898] [ 1.4510463 0.56553754] [ 0.67175039 0.39289585] [ 0.24957358 -0.11225323] [ 0.76510952 -0.4331749 ] [-0.36521848 0.61189523] [-0.31164943 1.31746906]] Center: [0.48149198 0.23647554]

Cluster 4: Data Points: [[2.1472291 4.37083105]] Center: [2.1472291 4.37083105]

Additionally, a plot is drawn, the clusters are colored, and the cluster centers are marked with a red x. I wanted all of this, but I have an additional column with categorical labels to the data and I want to shape my data points according to the respective category. For example,

shape_markers = {
    'Group 1': 's',  # Square
    'Group 2': 'o',  # Circle
    'Group 3': '^',  # Triangle
    'Group 4': 'v',  # Inverted Triangle
    'Group 5': 'd'  # Diamond
}

There are the clusters determined by the k-means algorithm then there are the labels I want to superimpose on the data. So, for example, we could imagine a blue data point that could be a circle or could be a triangle depending on its given label before and independent of the kmeans algorithm (which did determine the point belongs to the blue cluster). Here I am using 5 groups and 4 clusters (there's no reason to assume these need to be equal). The data array output from PCA is pca_data and is the numerical component of the dataframe, df, which has an additional column, Group, such that elements of Group are 'Group 1', ...., and 'Group 5'. How can I modify my code below to superimpose the shapes on the data according to the group labels and add a key to the plot to associate shapes with their Group value?

# Specify the number of clusters
k = 4

# Create a KMeans instance
kmeans = KMeans(n_clusters=k, init = 'random', n_init = 'auto')


# Fit the KMeans model to the data
kmeans.fit(pca_data)

# Get the cluster labels for each data point
labels = kmeans.labels_

# Get the cluster centers
centers = kmeans.cluster_centers_

# Print the cluster labels and centers
for i in range(k):
    cluster_points = pca_data[labels == i]
    cluster_center = centers[i]
    print(f"Cluster {i+1}:")
    print(f"Data Points: {cluster_points}")
    print(f"Center: {cluster_center}")
    print()

# Visualize the clusters 
import matplotlib.pyplot as plt

plt.scatter(pca_data[:, 0], pca_data[:, 1], c=labels)
plt.scatter(centers[:, 0], centers[:, 1], marker='X', color='red')
plt.xlabel('X-coordinate')
plt.ylabel('Y-coordinate')
plt.title('K-means Clustering')
plt.show()
$\endgroup$

1 Answer 1

1
$\begingroup$

Let's say in your pca_data list, every next element after x and y coordinate is their class label or Group name. Something like this... pca_data = [x1, y1, 'Group 1', x2, y2, 'Group 2', ....].
I have taken random points to make pca_data list.

You can use the code below for plotting data points.

import matplotlib.pyplot as plt
from collections import OrderedDict

pca_data = [1.87192346, -1.12568277, 'Group 1', 1.97012514, -0.70532312, 'Group 2',  3.45778709, -0.64678024, 'Group 2', 2.61029111, -2.32216733, 'Group 3', 0.84583072, 0.10252569, 'Group 1',0.17431096, 0.05538357, 'Group 2', 0.85267424, -0.37199898, 'Group 2',1.4510463, 0.56553754, 'Group 3', 0.67175039, 0.39289585, 'Group 1', 0.24957358, -0.11225323, 'Group 2',0.76510952, -0.4331749, 'Group 2',-0.36521848, 0.61189523, 'Group 1', -0.31164943, 1.31746906, 'Group 1']

# Lists of groups, shapes and colors
groups = ['Group 1', 'Group 2', 'Group 3', 'Group 4', 'Group 5']
shapes = ['s', 'o', '^', 'v', 'd']
colors = ['pink', 'blue', 'green', 'yellow', 'brown']

i = 0
while (i<len(pca_data)-1):
    g = pca_data[i+2]  
    idx = int(g[-1]) - 1;  # Geting the shape and group index, e.g., for Group 1, the shape is at 0th index.
    group = groups[idx] # Getting the group name
    plt.scatter(pca_data[i], pca_data[i+1], marker = shapes[idx], label= group, color = colors[idx])
    i+=3

handles, labels = plt.gca().get_legend_handles_labels()  
by_label = OrderedDict(zip(labels, handles))    # adding label values to dict to remove duplicate legend values
plt.legend(by_label.values(), by_label.keys())
plt.show()       

1: Scatter plot

Hope this helps!

$\endgroup$
1
  • 1
    $\begingroup$ thank you for the help! $\endgroup$
    – Squirtle
    Jul 18, 2023 at 19:28

Your Answer

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

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