K-Means聚类中多订单客户的集群归属问题求助
解决K-Means聚类中单个客户跨多集群的问题
我完全理解你的困扰——当你基于订单级数据做K-Means聚类时,同一个客户因为有多笔订单记录,自然会被分到不同的集群里,这根本没法支撑个性化推荐的需求。问题的核心在于你用错了聚类的粒度:应该从「订单级别」升级到「客户级别」来构建特征,再做聚类。
下面是具体的解决方案和优化后的代码:
第一步:重构数据到客户维度
首先需要把订单数据按客户ID聚合,计算每个客户的核心特征,这些特征才能真正代表客户的消费行为,比如:
- 总订单数(购买频次)
- 总消费金额(消费能力)
- 最后一次购买的时间间隔(客户活跃程度)
- 购买的商品品类数量(消费广度)
- 平均每单金额(客单价)
第二步:优化后的完整代码
import numpy as np import matplotlib.pyplot as plt import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans from sklearn.decomposition import PCA # 1. 加载数据集(假设包含客户ID、订单ID、金额、品类、下单日期等字段) dataset = pd.read_csv('FYP.csv') # 2. 按客户ID聚合,构建客户级特征(根据你的实际字段名调整) # 示例字段:CustomerID(客户ID)、OrderID(订单ID)、Amount(订单金额)、Category(商品品类)、OrderDate(下单日期) customer_features = dataset.groupby('CustomerID').agg( total_orders=('OrderID', 'nunique'), # 总订单数 total_spent=('Amount', 'sum'), # 总消费金额 avg_order_value=('Amount', 'mean'), # 平均订单金额 unique_categories=('Category', 'nunique'), # 购买的品类数量 last_order_days=('OrderDate', lambda x: (pd.Timestamp.now() - x.max()).days) # 最后一次购买距今天数 ).reset_index() # 3. 选择用于聚类的特征(排除客户ID) X = customer_features.drop('CustomerID', axis=1) # 4. 标准化特征(K-Means对特征尺度敏感,必须做标准化处理) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 5. 可选:PCA降维(用于可视化,聚类建议用标准化后的原始特征) pca = PCA(n_components=2) X_pca = pca.fit_transform(X_scaled) print(f"PCA成分解释方差比: {pca.explained_variance_ratio_}") # 6. 肘部法则确定最优聚类数 wcss = [] for i in range(1, 11): kmeans = KMeans(n_clusters=i, init='k-means++', max_iter=1000, n_init=10, random_state=42) kmeans.fit(X_scaled) wcss.append(kmeans.inertia_) plt.plot(range(1, 11), wcss) plt.title('The Elbow Method') plt.xlabel('Number of clusters') plt.ylabel('WCSS') plt.show() # 7. 训练K-Means模型(假设最优聚类数为3) kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=1000, n_init=10, random_state=42) customer_features['cluster_label'] = kmeans.fit_predict(X_scaled) # 8. 可视化聚类结果(用PCA降维后的二维数据) plt.scatter(X_pca[customer_features['cluster_label'] == 0, 0], X_pca[customer_features['cluster_label'] == 0, 1], s=100, c='red', label='Cluster 1: 高价值高频客户') plt.scatter(X_pca[customer_features['cluster_label'] == 1, 0], X_pca[customer_features['cluster_label'] == 1, 1], s=100, c='blue', label='Cluster 2: 新客户/低频次客户') plt.scatter(X_pca[customer_features['cluster_label'] == 2, 0], X_pca[customer_features['cluster_label'] == 2, 1], s=100, c='green', label='Cluster 3: 品类广泛的普通客户') plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=300, c='yellow', label='Centroids') plt.title('Clusters of Customers') plt.xlabel('PCA Component 1') plt.ylabel('PCA Component 2') plt.legend() plt.show() # 9. 分析每个集群的特征,为个性化推荐提供依据 cluster_summary = customer_features.groupby('cluster_label').mean() print("各集群特征统计:\n", cluster_summary)
额外优化建议
- 试试经典RFM模型:基于最近购买时间(Recency)、购买频次(Frequency)、消费金额(Monetary)三个核心特征,是电商客户分群的成熟方案,能快速区分高价值客户、流失客户等群体。
- 扩展特征维度:可以加入客户的商品品类偏好(如某品类购买占比)、是否使用优惠券、购买时段偏好等特征,让客户画像更精准。
- 算法灵活选择:如果客户数据分布不均匀,可尝试DBSCAN密度聚类,它能识别出异常点(如一次性大额购买的客户),而K-Means更适合球状分布的数据。
现在每个客户只会属于一个集群,你可以针对不同集群的特征制定个性化策略:比如给高价值客户推送专属折扣,给流失客户推送召回优惠券,给品类广泛的客户推荐互补商品。
内容的提问来源于stack exchange,提问作者Mahmoud Abdelazim Ali
相关产品推荐
相关产品推荐

