两组数据点之间的聚类-Python

2022-03-22 00:00:00 python pandas cluster-analysis

问题描述

我希望使用k-means聚类来绘制并返回每个集群的质心位置。下面将两组XY散点分组为6个群集。

使用下面的df,ABCD中的坐标被绘制为散点。我希望绘制并返回每个群集的质心。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans

df = pd.DataFrame(np.random.randint(-50,50,size=(100, 4)), columns=list('ABCD'))

fig, ax = plt.subplots()

Y_sklearn = df[['A','B','C','D']].values
 
model = KMeans(n_clusters = 4)
model.fit(Y_sklearn)
plt.scatter(Y_sklearn[:,0],Y_sklearn[:,1], c = model.labels_); 
plt.scatter(Y_sklearn[:,2],Y_sklearn[:,3], c = model.labels_); 

plt.show()     

解决方案

根据创建散点图的方式,我猜AB对应于第一组点的xy坐标,而CD对应于第二组点的xy坐标。如果是这样的话,您不能直接将Kmeans应用于数据帧,因为只有两个特性,即x和y坐标。找到质心其实很简单,您只需要model_zero.cluster_centers_

我们首先构建一个更便于可视化的数据帧

import numpy as np
# set the seed for reproducible datasets
np.random.seed(365)
# cov matrix of a 2d gaussian 
stds = np.eye(2)
# four cluster means 
means_zero = np.random.randint(10,20,(4,2))
sizes_zero = np.array([20,30,15,35])
# four cluster means 
means_one = np.random.randint(0,10,(4,2))
sizes_one = np.array([20,20,25,35])

points_zero = np.vstack([np.random.multivariate_normal(mean,stds,size=(size)) for mean,size in zip(means_zero,sizes_zero)])
points_one = np.vstack([np.random.multivariate_normal(mean,stds,size=(size)) for mean,size in zip(means_one,sizes_one)])
all_points = np.hstack((points_zero,points_one))

如您所见,这四个群集是由来自四个不同均值的高斯样本的采样点构成的。使用此数据帧,您可以按如下方式绘制它

import matplotlib.patheffects as PathEffects
from sklearn.cluster import KMeans

df = pd.DataFrame(all_points, columns=list('ABCD'))

fig, ax = plt.subplots(figsize=(10,8))

scatter_zero = df[['A','B']].values
scatter_one = df[['C','D']].values
 
model_zero = KMeans(n_clusters=4)
model_zero.fit(scatter_zero)
model_one = KMeans(n_clusters=4)
model_one.fit(scatter_one)

plt.scatter(scatter_zero[:,0],scatter_zero[:,1],c=model_zero.labels_,cmap='bwr'); 
plt.scatter(scatter_one[:,0],scatter_one[:,1],c=model_one.labels_,cmap='bwr'); 

# plot the cluster centers
txts = []
for ind,pos in enumerate(model_zero.cluster_centers_):
    txt = ax.text(pos[0],pos[1],
                  'cluster %i 
 (%.1f,%.1f)' % (ind,pos[0],pos[1]),
                  fontsize=12,zorder=100)
    txt.set_path_effects([PathEffects.Stroke(linewidth=5, foreground="aquamarine"),PathEffects.Normal()])
    txts.append(txt)
for ind,pos in enumerate(model_one.cluster_centers_):
    txt = ax.text(pos[0],pos[1],
                  'cluster %i 
 (%.1f,%.1f)' % (ind,pos[0],pos[1]),
                  fontsize=12,zorder=100)
    txt.set_path_effects([PathEffects.Stroke(linewidth=5, foreground="lime"),PathEffects.Normal()])
    txts.append(txt)
    
zero_mean = np.mean(model_zero.cluster_centers_,axis=0)
one_mean = np.mean(model_one.cluster_centers_,axis=0)
txt = ax.text(zero_mean[0],zero_mean[1],
              'point set zero',
              fontsize=15)
txt.set_path_effects([PathEffects.Stroke(linewidth=5, foreground="violet"),PathEffects.Normal()])
txts.append(txt)
txt = ax.text(one_mean[0],one_mean[1],
              'point set one',
              fontsize=15)
txt.set_path_effects([PathEffects.Stroke(linewidth=5, foreground="violet"),PathEffects.Normal()])
txts.append(txt)

plt.show()     

运行此代码,您将获得

相关文章