如何计算一维数据的平衡簇?

How to calculate balanced cluster of 1-d data?

我知道这里有许多其他问题,询问哪些聚类算法可用于一维数据,但我的问题是如何计算 平衡 聚类?

例如我有一个列表

l = [46, 48, 68, 46, 48, 68, 63, 62, 63, 63, 69, 54, 64, 61, 66, 54, 64, 67, 46, 48]

而且我知道我需要 3 个集群。但是使用 KMeans 聚类会给我

l = np.array(l, dtype=np.int16)
l = np.expand_dims(l, axis=1)

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3)
labels = kmeans.fit_predict(l)
print(labels)
> array([0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 0])

显然聚类是完全不平衡的:

print(np.unique(labels, return_counts=True))
> (array([0, 1, 2]), array([ 6, 12,  2], dtype=int64))

那么,有没有办法对 Python 中的一维数据进行聚类,并具有或多或少的 平衡 聚类?

您可以通过将数组分成 3 个分位数来完成此操作。在 pandas 中,您可以使用 pandas 中的 qcut,如下例所示。

l = [46, 48, 68, 46, 48, 68, 63, 62, 63, 63, 69, 54, 64, 61, 66, 54, 64, 67, 46, 48]

a = pd.qcut(l, 3, labels=[0, 1, 2])
print(a.to_numpy())
[0 0 2 0 0 2 1 1 1 1 2 0 2 1 2 0 2 2 0 0]

或者您可以只使用 numpy 中的 np.quantile 来手动计算分位数值,然后可以使用这些值来为新观察值分配聚类标签。

l = np.array([46, 48, 68, 46, 48, 68, 63, 62, 63, 63, 69, 54, 64, 61, 66, 54, 64, 67, 46, 48])

lower_q = np.quantile(l, 1/3)
upper_q = np.quantile(l, 2/3)

cl = []
for v in l:
    if v <= lower_q:
        cl.append(0)
    elif v > lower_q and v <= upper_q:
        cl.append(1)
    else: 
        cl.append(2)

cl = np.array(cl)
print(cl)