K-means聚类分组统计结果与Statistica不符,代码正确性咨询
首先,你的代码逻辑框架是正确的,但存在几个明显的问题和可能导致与Statistica结果不一致的原因,下面逐一拆解:
1. 代码中的直接错误
你在打印cardio == 0 count()时,实际计算的是cardio ==1的数量,这是明显的逻辑错误:
print('cardio == 0 count() for each cluster') for x in X: check = clusterDB_1[kmeans.labels_ == x] print(len(check[check['cardio'] == 1])) # 这里应该是 ==0
这个错误会直接导致你得到的cardio计数结果和预期不符。
2. 导致与Statistica结果不一致的核心原因
(1)KMeans的随机性差异
scikit-learn的KMeans默认使用随机初始化质心(init='k-means++'但仍有随机性),且默认n_init=10(运行10次取最优结果),而Statistica可能使用了不同的初始化策略、固定了随机种子,或者运行次数不同。这会导致聚类分组完全不同,最终统计量自然不一致。
解决方法:固定随机种子,确保聚类结果可复现:
kmeans = KMeans(n_clusters=8, random_state=42, n_init='auto').fit(clusterDB_1)
random_state=42固定随机种子,n_init='auto'让sklearn自动选择合适的运行次数(避免旧版本默认值差异)。
(2)数据预处理差异
检查Statistica是否对数据做了预处理:
- Age字段单位:你的数据集里Age可能是以天为单位(比如值在10000以上),Statistica可能将其转换为了年(除以365),而你在Python中直接使用原始值计算均值,这会导致Age的均值差异极大。
- 数据标准化/归一化:Statistica可能对Age、BMI做了标准化(比如Z-score)后再聚类,而你直接使用原始数据聚类,这会因为特征尺度差异(Age数值远大于BMI)导致聚类偏向Age维度,结果自然不同。
(3)聚类数量与参数匹配
确认Statistica中设置的聚类数是否也是8,以及是否有其他参数差异(比如距离度量,sklearn默认是欧氏距离,Statistica是否用了相同的距离)。
3. 优化后的代码(更高效且正确)
你可以不用多次循环,直接将聚类标签合并到数据框中,然后用groupby一次性计算所有需要的统计量,更简洁且不易出错:
import pandas as pd from sklearn.cluster import KMeans # 读取数据 dataset = pd.read_csv("C:/Users/../cardio_train_py.csv", sep=';') clusterDB_1 = dataset[['Age','BMI','cardio']].copy() # 固定随机种子,确保聚类结果可复现 kmeans = KMeans(n_clusters=8, random_state=42, n_init='auto').fit(clusterDB_1) # 将聚类标签加入数据框 clusterDB_1['cluster_label'] = kmeans.labels_ # 一次性计算所有统计量 cluster_stats = clusterDB_1.groupby('cluster_label').agg( Age_mean=('Age', 'mean'), Age_min=('Age', 'min'), Age_max=('Age', 'max'), Age_std=('Age', 'std'), BMI_mean=('BMI', 'mean'), BMI_min=('BMI', 'min'), BMI_max=('BMI', 'max'), BMI_std=('BMI', 'std'), cardio_0_count=('cardio', lambda x: (x == 0).sum()), cardio_1_count=('cardio', lambda x: (x == 1).sum()) ) print(cluster_stats)
4. 验证你的BMI结果异常
你给出的Python计算BMI结果中有一个值是166.57,这明显异常,说明你的数据集中可能存在BMI的异常值(比如输入错误),建议先检查数据:
print(clusterDB_1['BMI'].describe()) print(clusterDB_1[clusterDB_1['BMI'] > 100]) # 找出异常大的BMI值
这个异常值会严重影响聚类结果和统计量,Statistica可能自动过滤了异常值,而你的Python代码没有处理,这也是结果不一致的可能原因之一。
内容的提问来源于stack exchange,提问作者Marcin Miśkowiec

