当前位置: 首页 > news >正文

从Excel到3D图:一份内部数据的K-Means聚类与可视化完整实战记录(避坑xlrd与编码)

从Excel到3D图:K-Means聚类实战全流程解析

当业务部门甩过来一份销售数据Excel表格,要求"明天上班前给出客户分群报告"时,很多数据分析师的第一反应可能是打开Excel的筛选功能手动分类。但面对成百上千条多维数据,传统方法不仅效率低下,还容易受主观判断影响。本文将手把手带你用Python实现从原始Excel到三维可视化的完整分析闭环,特别针对中文编码、数据预处理等实际场景中的高频"坑点"提供解决方案。

1. 环境准备与数据读取

工欲善其事,必先利其器。我们先配置好分析环境:

# 基础环境安装(建议使用conda创建虚拟环境) conda create -n kmeans_analysis python=3.8 conda activate kmeans_analysis pip install numpy pandas scikit-learn matplotlib openpyxl xlrd

为什么选择openpyxl+xlrd组合?在读取老版本Excel文件(.xls)时,xlrd从2.0版本开始不再支持xlsx格式,而openpyxl对xlsx的兼容性更好。实际项目中常遇到混合格式的情况,建议同时安装这两个库。

读取数据时的典型问题及解决方案:

问题类型错误示例解决方案
中文路径UnicodeEncodeError路径前加r或使用os.path.normpath
空单元格NoneType异常增加if cell_value is not None判断
日期格式显示为浮点数使用xlrd.xldate_as_datetime转换
import os from pathlib import Path def read_excel_safe(file_path): """安全读取含中文路径的Excel文件""" try: file_path = str(Path(file_path).resolve()) if file_path.endswith('.xlsx'): from openpyxl import load_workbook wb = load_workbook(filename=file_path) ws = wb.active return [[cell.value for cell in row] for row in ws.iter_rows()] else: import xlrd wb = xlrd.open_workbook(file_path) ws = wb.sheet_by_index(0) return [[ws.cell_value(r, c) for c in range(ws.ncols)] for r in range(ws.nrows)] except Exception as e: print(f"读取失败: {str(e)}") return None

2. 数据预处理实战技巧

原始业务数据往往存在各种问题,直接扔进算法就像把没洗的菜下锅——结果可想而知。以下是三个关键预处理步骤:

2.1 缺失值处理的三重境界

  1. 简单删除:当缺失比例<5%时可用
    df.dropna(inplace=True)
  2. 均值/中位数填充:适合数值型特征
    from sklearn.impute import SimpleImputer imputer = SimpleImputer(strategy='median') df_filled = imputer.fit_transform(df)
  3. 模型预测填充:利用其他特征建立预测模型

2.2 特征标准化方法对比

业务数据常存在量纲差异(如销售额vs客户年龄),标准化是聚类的必要步骤:

方法公式适用场景Scikit-learn实现
MinMax(x-min)/(max-min)已知边界的数据MinMaxScaler
Z-Score(x-μ)/σ正态分布数据StandardScaler
Robust(x-median)/IQR含异常值数据RobustScaler
from sklearn.preprocessing import MinMaxScaler # 保留原始数据副本 raw_data = np.array(data) scaler = MinMaxScaler(feature_range=(0, 1)) normalized_data = scaler.fit_transform(raw_data)

2.3 分类变量编码策略

遇到地区、产品类别等文本字段时,需要转换为数值:

# 有序分类变量 from sklearn.preprocessing import OrdinalEncoder ordinal_encoder = OrdinalEncoder(categories=[['低', '中', '高']]) df['等级'] = ordinal_encoder.fit_transform(df[['等级']]) # 无序分类变量(避免引入虚假顺序) from sklearn.preprocessing import OneHotEncoder onehot = OneHotEncoder(sparse=False) encoded = onehot.fit_transform(df[['地区']])

3. K-Means建模的进阶技巧

3.1 如何科学确定K值

业务部门说"分4类",但数据真的适合分4类吗?三个验证方法:

  1. 肘部法则:观察SSE下降拐点

    sse = [] for k in range(1, 10): kmeans = KMeans(n_clusters=k) kmeans.fit(data) sse.append(kmeans.inertia_) plt.plot(range(1,10), sse, 'bx-')
  2. 轮廓系数:评估聚类紧密度

    from sklearn.metrics import silhouette_score sil_score = silhouette_score(data, kmeans.labels_)
  3. Gap统计量:比较实际数据与参考分布

3.2 处理非凸聚类的小技巧

标准K-Means假设聚类是球形的,当遇到如下情况时:

  • 尝试谱聚类

    from sklearn.cluster import SpectralClustering spec = SpectralClustering(n_clusters=4, affinity='nearest_neighbors')
  • 使用核K-Means

    from sklearn.cluster import KMeans from sklearn.metrics.pairwise import rbf_kernel gamma = 0.1 K = rbf_kernel(data, gamma=gamma) kmeans = KMeans(n_clusters=4).fit(K)

3.3 聚类结果评估矩阵

不要只依赖模型输出,要用业务指标验证:

# 计算每个簇的统计量 df['cluster'] = kmeans.labels_ cluster_stats = df.groupby('cluster').agg({ '销售额': ['mean', 'count'], '利润率': 'median' })

4. 三维可视化与结果输出

4.1 交互式3D绘图技巧

静态图难以观察数据全貌,推荐使用:

import plotly.express as px fig = px.scatter_3d(df, x='特征1', y='特征2', z='特征3', color='cluster', hover_name='客户ID') fig.update_traces(marker_size=5) fig.show()

实用参数调整:

  • opacity=0.7解决点重叠问题
  • size_max=10控制点大小范围
  • animation_frame='时间字段'制作动态演变图

4.2 结果保存的最佳实践

避免中文乱码的CSV输出方案:

with open('聚类结果.csv', 'w', encoding='utf-8-sig', newline='') as f: writer = csv.writer(f) writer.writerow(['原始索引', '聚类标签'] + feature_names) for i, (orig, label) in enumerate(zip(raw_data, labels)): writer.writerow([i, label] + list(orig))

4.3 制作可交互报告

用Pyecharts生成HTML分析报告:

from pyecharts.charts import Scatter3D from pyecharts import options as opts scatter3d = ( Scatter3D() .add("", [(d[0], d[1], d[2]) for d in data], grid3d_opts=opts.Grid3DOpts(width=100, depth=100)) .set_global_opts(title_opts=opts.TitleOpts(title="客户分群3D视图")) ) scatter3d.render("cluster_3d.html")

5. 业务落地常见问题

为什么聚类结果不符合业务直觉?

  • 检查特征相关性:高相关特征会导致维度浪费
  • 尝试特征组合:如"客单价×购买频率"可能比单独使用更有意义
  • 考虑非线性关系:先用PCA降维观察数据结构

如何向非技术人员解释聚类结果?

  1. 为每个簇起业务名称(如"高价值休眠客户")
  2. 制作雷达图对比簇特征:
    from pyecharts.charts import Radar radar = Radar().add_schema(schema).add("簇1", values1)
  3. 提供典型客户案例(不要只用统计数字)

模型迭代策略:

  • 定期用新数据验证聚类稳定性
  • 设置业务指标监控(如不同簇的转化率变化)
  • 建立自动化重训练机制(如每月第一个周一自动运行)
http://www.cnnetsun.cn/news/2566829.html

相关文章:

  • 瑞德克斯平台:从风险提示看平台责任意识
  • 【Spring Boot 认证登录注册模块全解析】:JWT+BCrypt+Redis 企业级实践
  • DELL G3装Ubuntu后WiFi挂了?手把手教你精准查询网卡型号并找对驱动(避坑指南)
  • 告别游戏卡顿!保姆级教程:在Win10上彻底搞定Antimalware Service高占用
  • 趋势科技提醒注意已遭利用的 Apex One 0day 漏洞
  • zotero修改:(1)英文作者三人以上出现“等”
  • 文档格式兼容性挑战与渐进式渲染优化:docxjs库的Web文档渲染架构解析
  • 智能手机多摄像头高光谱成像系统设计与实现
  • 告别外部中断!用EnableInterrupt库轻松搞定Arduino Nano多通道PWM读取(附完整代码)
  • 从频域到时域:聊聊宽带波束形成的两种实现路径与工程选型心得
  • Unity性能适配实战:用SystemInfo判断玩家设备,动态调整画质和特效(附完整代码)
  • Linux下MariaDB 10安装与配置指南
  • 基于OTA芯片的三相正弦波压控振荡器设计与实现
  • 协程详细介绍
  • D37: 周复盘:ToB 项目的 AI 落地方法论
  • 安卓手机安装龙虾openclaw接入deepseek
  • Win10系统清理避坑指南:你的BAT脚本真的安全吗?盘点那些不能乱删的文件
  • 支付宝商户池:收款防风控专属安全通道
  • 一匹来自顺德的布,凭什么走上国际时装周
  • html2pdf-chrome:一个 HTML 转 PDF 的 Go 库 / 服务,依旧是现阶段效果最佳的
  • Unity JSON解析救星:Newtonsoft.Json-for-Unity实战指南
  • C++基础 类和对象(三)
  • 别再折腾驱动了!用DKMS一劳永逸管理你的Linux网卡(以RTL8822CE/Ubuntu 18.04为例)
  • 别再死记硬背了!用Wirtinger导数轻松搞定复数求导(附Python代码验证)
  • 别再傻等自动下载了!手把手教你从国内镜像站搞定Wine 5.0的mono和gecko插件
  • LOOKAHEAD REASONING:大型推理模型的并行加速技术
  • RK3588 Debian 系统安装与WiFi/SSH配置笔记
  • FPG财盛国际:从风险提示看平台责任意识
  • Linux系统启动慢?从UEFI的DXE阶段入手,优化驱动加载让你的开机快人一步
  • 【复现】中国上市公司全要素生产率测算与分析(论文+数据)