缘由

艺多不压身

碎碎念

我们继续飞行在云层和雾气之间,飞行在一个无光无影的空洞世界中。 ——《风沙星辰》

Ref

K-means clustering with tidy data principles – tidymodels

代码

利用kmeans 选择聚类数

library(tidymodels)
library(ggplot2)
 
#️⃣ Step 1 构造模拟数据
# 目的:生成三类点,便于测试聚类算法
# 优点:数据结构已知,能验证算法效果
set.seed(27)
centers <- tibble(
	cluster = factor(1:3),
	num_points = c(100, 150, 50),  # 每簇点数
	x1 = c(5, 0, -3),              # x1中心
	x2 = c(-1, 1, -2)              # x2中心
)
 
#️⃣ Step 2 生成带标签的数据
# 目的:为每个簇中心生成正态分布点
# 优点:既有真实标签又保留随机性
labelled_points <-
	centers %>%
	mutate(
		x1 = map2(num_points, x1, function(n, center) rnorm(n, center)),
		x2 = map2(num_points, x2, function(n, center) rnorm(n, center))
	) %>%
	select(-num_points) %>%
	unnest(cols = c(x1, x2))
 
# 可视化标签数据
ggplot(labelled_points, aes(x1, x2, color = cluster)) +
	geom_point(alpha = 0.3)
 
 
#️⃣ Step 3 运行 K-means 聚类
# 目的:对无标签数据进行聚类
# 优点:检验算法能否恢复原簇结构
points <- labelled_points %>% select(-cluster)
kclust <- kmeans(points, centers = 3)
kclust
 
# 输出统计信息
augment(kclust, points)
tidy(kclust)
glance(kclust)
 
 
#️⃣ Step 4 探索不同聚类数
# 目的:尝试 k=1 到 9,观察聚类效果
# 优点:帮助确定合适的簇数
kclusts <-
	tibble(k = 1:9) %>%
	mutate(
		kclust = map(k, ~kmeans(points, .x)),
		tidied = map(kclust, tidy),
		glanced = map(kclust, glance),
		augmented = map(kclust, augment, points)
	)
 
clusters <- kclusts %>% unnest(cols = c(tidied))
assignments <- kclusts %>% unnest(cols = c(augmented))
clusterings <- kclusts %>% unnest(cols = c(glanced))
 
 
#️⃣ Step 5 可视化不同聚类数
# 目的:展示不同 k 下的聚类划分
# 优点:直观比较聚类边界和样本分配
p1 <-
	ggplot(assignments, aes(x = x1, y = x2)) +
	geom_point(aes(color = .cluster), alpha = 0.8) +
	facet_wrap(~ k)
p1
 
 
#️⃣ Step 6 计算总平方和  手肘法选取簇数
# 目的:评估不同簇数下的聚类紧凑度
# 优点:为手肘法选 k 提供数据
ggplot(clusterings, aes(k, tot.withinss)) +
	geom_line() +
	geom_point()