手把手教你用Python和Matplotlib给三维数据做K-Means聚类可视化(附完整代码)
三维数据聚类实战:用Python实现K-Means算法与可视化全流程
在数据分析领域,聚类算法能帮助我们发现数据中隐藏的自然分组。想象一下,你手头有一组包含三个维度的用户行为数据——比如浏览时长、点击次数和购买金额。如何快速识别出具有相似行为模式的用户群体?K-Means算法配合三维可视化就是你的理想选择。本文将带你从零开始,用Python实现完整的聚类分析流程,并生成直观的三维效果图。
1. 环境准备与数据理解
在开始编码之前,我们需要确保开发环境配置正确。推荐使用Anaconda创建Python 3.8+的虚拟环境,它能方便地管理各种数据分析所需的依赖包。
核心工具包安装 :
pip install numpy pandas matplotlib scikit-learn
三维数据集通常以以下几种形式存在:
- CSV/Excel表格中的三列数值数据
- 数据库查询结果中的三个特征字段
- 通过API获取的JSON格式三维坐标
无论原始数据格式如何,最终我们需要将其转换为NumPy数组或Pandas DataFrame,结构如下:
| 特征1 | 特征2 | 特征3 |
|---|---|---|
| 1.2 | 3.4 | 0.5 |
| 2.1 | 1.8 | 4.2 |
| ... | ... | ... |
提示:如果各特征量纲差异较大(如年龄0-100 vs 收入0-100000),务必先进行标准化处理,避免量纲影响聚类结果。
2. 数据预处理:为聚类做好准备
高质量的数据预处理是成功聚类的前提。对于三维数据,我们需要重点关注以下几个方面:
2.1 缺失值处理
检查数据完整性是第一步:
import pandas as pd
# 假设数据已加载到df中
print(df.isnull().sum())
# 简单填充策略
df.fillna(df.mean(), inplace=True)
2.2 特征标准化
不同尺度的特征会导致距离计算偏差,MinMax标准化是最常用的方法之一:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(df)
标准化前后数据分布对比:
| 处理步骤 | 特征1范围 | 特征2范围 | 特征3范围 |
|---|---|---|---|
| 原始数据 | 0-1000 | 0-50 | 0-1 |
| 标准化后 | 0-1 | 0-1 | 0-1 |
2.3 异常值检测
三维数据中的异常点会显著影响聚类中心位置:
from scipy import stats
# 使用Z-score检测异常值
z_scores = stats.zscore(scaled_data)
abs_z_scores = np.abs(z_scores)
filtered_entries = (abs_z_scores < 3).all(axis=1)
clean_data = scaled_data[filtered_entries]
3. K-Means算法实现与调优
Scikit-learn提供了高效的K-Means实现,但我们先理解其核心原理。
3.1 算法核心步骤
- 初始化 :随机选择K个点作为初始聚类中心
- 分配阶段 :将每个点分配到最近的聚类中心
- 更新阶段 :重新计算每个簇的中心点
- 迭代 :重复2-3步直到中心点不再显著变化
手动实现简化版K-Means:
from sklearn.metrics import pairwise_distances_argmin_min
def manual_kmeans(data, k, max_iter=100):
# 随机初始化中心点
centers = data[np.random.choice(data.shape[0], k, replace=False)]
for _ in range(max_iter):
# 分配点到最近中心
labels, _ = pairwise_distances_argmin_min(data, centers)
# 更新中心点
new_centers = np.array([data[labels==i].mean(0) for i in range(k)])
# 检查收敛
if np.allclose(centers, new_centers):
break
centers = new_centers
return labels, centers
3.2 使用Scikit-learn高效实现
生产环境推荐使用优化过的库实现:
from sklearn.cluster import KMeans
# 确定最佳K值 - 肘部法则
inertia = []
for k in range(1, 10):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(scaled_data)
inertia.append(kmeans.inertia_)
# 可视化寻找"肘点"
plt.plot(range(1, 10), inertia, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('Inertia')
plt.show()
3.3 聚类质量评估
除了肘部法则,轮廓系数也是评估聚类效果的重要指标:
from sklearn.metrics import silhouette_score
best_k = 3 # 假设通过肘部法则确定
kmeans = KMeans(n_clusters=best_k, random_state=42)
labels = kmeans.fit_predict(scaled_data)
score = silhouette_score(scaled_data, labels)
print(f"轮廓系数: {score:.3f}")
轮廓系数解读:
- 接近1:样本离其他簇很远,聚类效果好
- 接近0:样本处在决策边界
- 接近-1:样本可能被分配到错误簇
4. 三维可视化实战
Matplotlib的mplot3d工具包提供了强大的三维可视化能力。
4.1 基础三维散点图
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 为不同簇设置不同颜色
colors = ['r', 'g', 'b', 'y', 'c', 'm']
for i in range(best_k):
cluster_data = scaled_data[labels == i]
ax.scatter(cluster_data[:, 0],
cluster_data[:, 1],
cluster_data[:, 2],
c=colors[i],
label=f'Cluster {i+1}',
s=50, alpha=0.6)
# 标记聚类中心
centers = kmeans.cluster_centers_
ax.scatter(centers[:, 0], centers[:, 1], centers[:, 2],
c='black', marker='x', s=200, linewidths=3)
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.set_zlabel('Feature 3')
plt.legend()
plt.title('3D K-Means Clustering Result')
plt.tight_layout()
plt.show()
4.2 可视化增强技巧
旋转动画 可以让三维结构更清晰:
from matplotlib.animation import FuncAnimation
def update(frame):
ax.view_init(elev=20, azim=frame)
return fig,
ani = FuncAnimation(fig, update, frames=np.arange(0, 360, 2), interval=50)
ani.save('cluster_rotation.gif', writer='pillow', fps=15)
交互式可视化 使用Plotly效果更佳:
import plotly.express as px
df_plot = pd.DataFrame(scaled_data, columns=['Feat1', 'Feat2', 'Feat3'])
df_plot['Cluster'] = labels.astype(str)
fig = px.scatter_3d(df_plot, x='Feat1', y='Feat2', z='Feat3',
color='Cluster', opacity=0.7,
title='Interactive 3D Clustering')
fig.update_traces(marker_size=5)
fig.show()
4.3 高级可视化元素
添加决策边界能更清晰展示聚类区域:
# 创建网格点
x_min, x_max = scaled_data[:, 0].min() - 0.1, scaled_data[:, 0].max() + 0.1
y_min, y_max = scaled_data[:, 1].min() - 0.1, scaled_data[:, 1].max() + 0.1
z_min, z_max = scaled_data[:, 2].min() - 0.1, scaled_data[:, 2].max() + 0.1
xx, yy, zz = np.meshgrid(np.linspace(x_min, x_max, 10),
np.linspace(y_min, y_max, 10),
np.linspace(z_min, z_max, 10))
# 预测网格点类别
grid_points = np.c_[xx.ravel(), yy.ravel(), zz.ravel()]
grid_labels = kmeans.predict(grid_points)
# 绘制半透明决策区域
ax.scatter(grid_points[:, 0], grid_points[:, 1], grid_points[:, 2],
c=grid_labels, alpha=0.02, s=1)
5. 实战案例:用户分群分析
假设我们有一组电商用户的三维行为数据:
- X轴:每月访问次数(5-50次)
- Y轴:平均停留时长(1-30分钟)
- Z轴:转化率(0%-20%)
应用完整流程后的分析步骤:
- 数据清洗 :去除机器人访问(异常高访问量+零转化)
- 标准化处理 :MinMax标准化各维度
- 确定K值 :肘部法则确定最佳K=4
- 聚类分析 :得到4个典型用户群体
- 三维可视化 :清晰展示群体分布特征
典型聚类结果解读:
| 群体 | 访问频率 | 停留时长 | 转化率 | 营销策略建议 |
|---|---|---|---|---|
| 1 | 高 | 中 | 高 | 忠诚客户,推荐高价值商品 |
| 2 | 高 | 长 | 低 | 浏览型用户,需要促销刺激 |
| 3 | 低 | 短 | 低 | 潜在流失客户,需召回策略 |
| 4 | 中 | 中 | 中 | 普通用户,常规运营维护 |
三维可视化中可能会发现:
- 群体2和群体3在某个维度上非常接近
- 群体1明显与其他群体分离
- 存在少量边界点难以明确分类
这些洞察能帮助运营团队制定更精准的营销策略。比如,对处于群体2和群体3边界上的用户,可以采用A/B测试来确定最适合的沟通方式。
更多推荐

所有评论(0)