▶️ 查看代码
1 2 3
2 500.00
3 10.05 499.08
4 801.09 301.20 800.00
第19讲:层次聚类(二)——标准化、聚类画像与实战
2026年06月03日
scale() 消除量纲影响,财务数据必须执行scale → dist → hclust → plot → cutree → rect.hclust
本讲核心:让聚类结果"开口说话"
本讲重点
对聚类产生后的"群体特征"进行文字描述——即聚类画像(Cluster Profiling)
聚类的终点不是一张谱系图,而是能够回答"每一类客户/学校/企业是什么特征?"
本讲难点
标准化(Standardization)在实际财务数据中的必要性
财务数据的典型挑战:
10⁸
10⁰
三个能力层次(本讲目标):
| 层次 | 目标 |
|---|---|
| 🔵 低阶 | 巩固 dist 和 hclust 的代码流程 |
| 🟡 中阶 | 熟练使用 rect.hclust() 切分;理解聚类中心的财务含义 |
| 🔴 高阶 | 根据企业特征独立完成聚类画像,制定差异化财务策略 |
标准化 vs 不标准化——真实的对比
假设我们有 4 家上市公司(A、B、C、D),两项财务指标如下: * \(x_1\) (核心质地指标):如净资产收益率、研发投入比。数值小,但反映本质。 * \(x_2\) (资产规模指标):量纲极大的绝对数(百万元)。
| 样本企业 | \(x_1\) (核心质地) | \(x_2\) (资产规模) |
|---|---|---|
| A | 0 | 1000 |
| B | 1 | 1500 |
| C | 10 | 1001 |
| D | 12 | 1801 |
🤔 思考:如果让你把它们分成两类,你会怎么分?为什么?
关键问题:量纲不同时,算法"看到"的距离已经失真
如果我们直接把原始数据扔进欧氏距离公式: \[d = \sqrt{(\Delta x_1)^2 + (\Delta x_2)^2}\]
1 2 3
2 500.00
3 10.05 499.08
4 801.09 301.20 800.00
未标准化,计算出来的欧式距离显示A和C较近,其次是B和D较近。
注记
标准化后,量纲较大的\(x_2\)不再有那么大的影响力。
scale() 做了什么?
\[z_i = \frac{x_i - \bar{x}}{s_x}\]
标准化后每个变量:均值 = 0,标准差 = 1,所有变量处于同等地位
提示
黄金法则:只要变量的量纲不同(或数量级差异超过 10 倍),聚类前必须 scale()!
| 场景 | 是否必须标准化 |
|---|---|
| 资产(亿)+ 周转率(次) | ✅ 必须 |
| 花瓣长(cm)+ 花瓣宽(cm) | ✅ 建议 |
| 全部为百分比数据 | ⚠️ 视情况 |
| 已经是标准分数(Z-score) | ❌ 无需 |
聚类画像:从分组标签到群体特征描述
聚类的终点不是数字,而是能够"说出来"的群体故事
提示
聚类命名示例:
聚类中心 = 该类的"典型代表",是群体特征描述的数字基础
注记
解读聚类中心的三个步骤:
exp())才有业务含义聚类不只适用于数值型变量
现实数据往往是"混合型"的
注记
前两列(年龄、年收入)是数值型,可直接计算欧氏距离;后三列(学历、是否购房、风险偏好)是分类型,不能直接计算距离。混合数据需要专门的距离方法。
思路一:简单匹配(Simple Matching)——二元变量
对于只有两个取值的二元变量(是/否、男/女),定义:
\[d_{ij}^{\text{二元}} = \begin{cases} 0 & \text{两者取值相同} \\ 1 & \text{两者取值不同} \end{cases}\]
思路二:虚拟变量编码(One-Hot Encoding)——多分类变量
将有 \(k\) 个类别的变量展开为 \(k\) 列 0/1 虚拟变量,再用欧氏距离或曼哈顿距离:
学历(原始) → 本科 硕士 博士
"本科" → 1 0 0
"硕士" → 0 1 0
"博士" → 0 0 1
警告
虚拟变量列数越多,数值型变量的相对权重越小——列数多时仍需标准化或权重调整。
思路三:Gower 距离——混合型数据的通用方案
\[d^{\text{Gower}}_{ij} = \frac{\sum_{f=1}^{p} w_f \cdot d^{(f)}_{ij}}{\sum_{f=1}^{p} w_f}\]
对每一个变量 \(f\) 单独计算"部分距离",再加权平均:
| 变量类型 | 部分距离 \(d^{(f)}_{ij}\) |
|---|---|
| 连续型 | \(\|x_{if} - x_{jf}\| / \text{range}_f\),归一化到 [0,1] |
| 二元型 | 0(相同)或 1(不同) |
| 名义型(多分类) | 0(相同)或 1(不同) |
| 有序型(等级) | 按秩归一化后取差值 |
cluster 包的 daisy() 函数自动识别变量类型
library(cluster)
# 混合型数据示例
customers <- data.frame(
年龄 = c(28, 45, 31, 52),
年收入_万 = c(12, 38, 15, 60),
学历 = factor(c("本科","硕士","本科","博士"),
levels=c("本科","硕士","博士"), ordered=TRUE), # 有序因子
是否购房 = factor(c("否","是","否","是")), # 名义因子
风险偏好 = factor(c("激进","保守","激进","保守")) # 名义因子
)
# daisy() 自动处理混合类型,metric="gower" 时无需预先标准化数值列
gower_dist <- daisy(customers, metric = "gower")
round(as.matrix(gower_dist), 3) 1 2 3 4
1 0.000 0.750 0.038 1.000
2 0.750 0.000 0.713 0.250
3 0.038 0.713 0.000 0.963
4 1.000 0.250 0.963 0.000
[1] 1 2 1 2
提示
关键优势:daisy() 自动识别因子、有序因子和数值列,无需手动编码;Gower 距离内置了对每个变量的归一化,数值列和分类列天然处于同等权重,通常不必再额外 scale()。
重要
常见误区:对分类变量强行使用数值编码(如将学历编为 1/2/3),隐含了"博士与本科的距离是硕士与本科的两倍"这样的假设。若没有明确理由支持这种等距假设,应使用 ordered factor 配合 daisy(),让算法按秩归一化处理。
college 数据集完整分析流程
项目背景:college 数据集包含美国高校的办学信息,对私立学校进行聚类分析,探索私立高校的分类特征。
library(dplyr)
# 读入数据,指定变量类型
college <- read.csv("college.csv",
colClasses = c(rep("character", 2), rep("numeric", 17))) #指定前两列为字符型,后17列为数值型
# 只保留私立学校
college <- college %>% filter(Private == "Yes")
str(college)
# 删除 Private 列(第2列)
college <- college[-2]
# college <- college %>%
# select(-2)
# 对有极值的连续变量进行对数变换
college <- college %>%
mutate(
Apps = log(Apps),
Accept = log(Accept),
Enroll = log(Enroll),
F.Undergrad = log(F.Undergrad),
P.Undergrad = log(P.Undergrad),
Books = log(Books),
Personal = log(Personal),
Expend = log(Expend)
)
hist(college$Expend)注记
为什么对这些变量做对数变换? Apps(申请数)等变量存在极右偏(少数超级名校申请量极大),对数变换可压缩极值、使分布更接近正态,令距离计算更稳健。
将所有连续变量(2–18列)进行标准化处理,并查看前三行记录。
Apps Accept Enroll Top10perc Top25perc F.Undergrad P.Undergrad
[1,] 0.3200 0.3674 1.01626 -0.3546 -0.2531 1.0116 0.7442
[2,] 0.6123 0.8946 0.55596 -0.7468 -1.4273 0.9132 1.2961
[3,] 0.1602 0.2302 -0.01043 -0.4107 -0.3552 -0.3761 -0.3851
Outstate Room.Board Books Personal PhD Terminal S.F.Ratio
[1,] -1.1765 -1.1803 -0.6306 1.5082 -0.06304 -0.0346 1.46494
[2,] 0.1290 1.7104 1.3800 0.6890 -2.42603 -3.1413 -0.21187
[3,] -0.1488 -0.7673 -1.0942 0.1484 -1.04282 -0.8113 -0.01293
perc.alumni Expend Grad.Rate
[1,] -1.1201 -0.7479 -0.5372
[2,] -0.7976 0.2430 -0.7760
[3,] 0.3314 -0.2168 -0.8954
提示
解读:标准化后,每列的均值 ≈ 0,标准差 = 1。正值表示该校在该指标上高于平均水平,负值表示低于平均。
对标准化数据做层次聚类(平均链接法),画谱系图。
注记
谱系图分析:观察纵轴高度的"大跳跃"位置——两个相邻合并步骤之间距离差最大处,是确定 k 值的参考依据。本数据集高度跳跃约在 6–8 之间,提示可考虑 k=4 或 k=5。
groups
1 2 3 4 5
520 41 1 2 1
注记
解读:各类样本数差异反映了私立高校的分布不均匀性——某些类型的学校占多数,另一些属于"特色小众"类型。
Name Apps Accept Enroll Top10perc Top25perc
1 Abilene Christian University 7.415 7.116 6.581 23 52
2 Adelphi University 7.690 7.562 6.238 16 29
3 Adrian College 7.264 7.000 5.817 22 50
4 Agnes Scott College 6.033 5.855 4.920 60 89
5 Alaska Pacific University 5.263 4.984 4.007 16 44
6 Albertson College 6.375 6.172 5.063 38 62
F.Undergrad P.Undergrad Outstate Room.Board Books Personal PhD Terminal
1 7.967 6.286 7440 3300 6.109 7.696 70 78
2 7.895 7.112 12280 6450 6.620 7.313 29 30
3 6.943 4.595 11250 3750 5.991 7.060 53 66
4 6.234 4.143 12960 5450 6.109 6.774 92 97
5 5.517 6.767 7560 4120 6.685 7.313 76 72
6 6.519 3.714 13500 3335 6.215 6.515 67 73
S.F.Ratio perc.alumni Expend Grad.Rate cluster
1 18.1 12 8.860 60 1
2 12.2 16 9.262 56 1
3 12.9 30 9.075 54 1
4 7.7 37 9.853 59 1
5 11.9 2 9.299 15 1
6 9.4 11 9.183 55 1
注记
图形分析:
# A tibble: 2 × 3
cluster 均值_Apps 均值_Accept
<int> <dbl> <dbl>
1 1 6.97 6.70
2 2 8.89 8.20
Group.1 Apps Accept
1 1 6.972 6.696
2 2 8.891 8.201
重要
结果解读示例:第1类均值_Apps < 第2类,说明第2类学校接收的申请量更多,可能为更知名或规模更大的私立高校;录取数均值同方向变化则进一步验证这一判断。
标准化是聚类的生命线:量纲差异超过 10 倍,不标准化的聚类结果必然失真;scale() 是黄金法则
rect.hclust() 一行可视化:在谱系图上直接框出分组,是"确认 k 值"的最直观方式
聚类中心的业务含义:group_by(cluster) %>% summarise(mean) 计算各类均值,是"读懂分组"的核心操作
聚类画像三步法:计算聚类中心 → 横向对比关键指标 → 用业务语言为群体命名
分类变量不能直接算距离:使用 daisy(metric="gower") 处理混合型数据;有序变量设为 ordered factor,名义变量设为普通 factor,让算法正确识别
高阶目标:根据群体特征(保守型 vs 激进型)制定差异化策略,这才是聚类的真正价值
提示
高阶思考:聚类不是终点,画像与策略才是。在实际项目中,对每一类群体,都应能回答:"这类客户/学校/企业的核心特征是什么?对应的管理/经营/投资策略应该如何差异化?"
第19讲:层次聚类(二)——标准化、聚类画像与实战
「聚类的价值,不在于把数据分成几堆,而在于为每一堆找到它独有的名字——这个名字,是数据给决策者的礼物。」
数据挖掘与R语言 | 层次聚类(二)