含多离散与分类变量的数据集:Python聚类选型及Kmeans/Kmodes适用性探讨
针对混合离散/分类变量数据集的Python聚类方案
一、K-Means与K-Modes的适用性分析
K-Means
- 不适用。K-Means依赖欧氏距离计算样本相似度,仅适配连续数值型变量。你的数据中包含大量分类变量(如
Gender、Department),若强行将分类变量编码为数值(如0/1)后使用K-Means,会错误赋予分类变量不存在的数值大小关系,导致聚类结果完全失真。
K-Modes
- 仅适合纯分类变量场景。K-Modes使用匹配距离(统计样本间相同分类属性的数量)聚类,但会完全忽略
Age、Salary、Distance等连续变量的信息,浪费数据中的关键特征,因此也不是你的数据集的最优选择。
二、推荐的混合数据聚类方法
1. K-Prototypes(首选)
K-Prototypes是K-Means和K-Modes的结合,专门针对混合连续+分类变量的数据集设计:
- 对连续变量使用欧氏距离,对分类变量使用匹配距离
- 聚类过程中同时优化两类变量的损失
- Python中可通过
kmodes库实现
代码示例:
import pandas as pd from kmodes.kprototypes import KPrototypes # 加载数据集 data = pd.DataFrame({ 'Age': [41, 24], 'Gender': ['Female', 'Male'], 'BusinessTravel': ['Frequent', 'Rarely'], 'Department': ['Sales', 'HR'], 'Distance': [12, 22], 'Education': [5, 4], 'MaritalStatus': ['Married', 'Single'], 'Salary': [5000, 3400], 'YearsWorked': [4, 1], 'Satisfaction': [4, 3] }) # 指定分类变量的列索引 cat_cols = [1, 2, 3, 6] data_array = data.values # 训练K-Prototypes模型 kproto = KPrototypes(n_clusters=2, init='Cao', verbose=2) clusters = kproto.fit_predict(data_array, categorical=cat_cols) # 合并聚类结果到原数据 data['Cluster'] = clusters print(data)
2. Gower距离 + 层次聚类/DBSCAN
Gower距离是专门为混合类型数据设计的相似度度量,能同时处理:
- 连续变量:标准化后计算相对差异
- 分类变量:匹配度(相同为1,不同为0)
- 有序离散变量:按等级差异计算
代码示例(Gower距离+层次聚类):
import pandas as pd import gower from sklearn.cluster import AgglomerativeClustering # 加载数据集 data = pd.DataFrame({ 'Age': [41, 24], 'Gender': ['Female', 'Male'], 'BusinessTravel': ['Frequent', 'Rarely'], 'Department': ['Sales', 'HR'], 'Distance': [12, 22], 'Education': [5, 4], 'MaritalStatus': ['Married', 'Single'], 'Salary': [5000, 3400], 'YearsWorked': [4, 1], 'Satisfaction': [4, 3] }) # 计算Gower距离矩阵 distance_matrix = gower.gower_matrix(data) # 执行层次聚类 agg_clustering = AgglomerativeClustering(n_clusters=2, affinity='precomputed', linkage='average') clusters = agg_clustering.fit_predict(distance_matrix) data['Cluster'] = clusters print(data)
3. 编码+传统聚类(备选)
如果不想使用专门的混合数据算法,可对分类变量进行独热编码,再结合标准化的连续变量使用K-Means或DBSCAN,但这种方法存在高维稀疏性问题,仅适合分类变量较少的场景:
import pandas as pd from sklearn.preprocessing import OneHotEncoder, StandardScaler from sklearn.compose import ColumnTransformer from sklearn.cluster import KMeans # 加载数据集 data = pd.DataFrame({ 'Age': [41, 24], 'Gender': ['Female', 'Male'], 'BusinessTravel': ['Frequent', 'Rarely'], 'Department': ['Sales', 'HR'], 'Distance': [12, 22], 'Education': [5, 4], 'MaritalStatus': ['Married', 'Single'], 'Salary': [5000, 3400], 'YearsWorked': [4, 1], 'Satisfaction': [4, 3] }) # 定义预处理管道:连续变量标准化,分类变量独热编码 preprocessor = ColumnTransformer( transformers=[ ('num', StandardScaler(), ['Age', 'Distance', 'Salary', 'YearsWorked', 'Education', 'Satisfaction']), ('cat', OneHotEncoder(), ['Gender', 'BusinessTravel', 'Department', 'MaritalStatus']) ]) processed_data = preprocessor.fit_transform(data) # K-Means聚类 kmeans = KMeans(n_clusters=2, random_state=42) clusters = kmeans.fit_predict(processed_data) data['Cluster'] = clusters print(data)
三、总结
- 优先选择K-Prototypes,它能同时利用连续和分类变量的信息,实现高效且合理的聚类
- 若需要更灵活的距离度量,可使用Gower距离+层次聚类/DBSCAN
- 独热编码+传统聚类仅作为备选,不推荐用于分类变量较多的数据集
内容的提问来源于stack exchange,提问作者Dylariant
相关产品推荐
相关产品推荐

