基于Country和Year分层对Value变量做K-Means聚类并分类案例
问题解决思路与代码实现
核心问题分析
- 分层逻辑失效:大概率是部分
Country-Year分组的样本量不足3(K-Means分3类至少需要3个样本),导致聚类无法正常执行;也可能是分组后的数据处理逻辑有误,未正确在组内独立执行聚类。 - K-Means不收敛警告:默认迭代次数(10次)太少,或初始聚类中心选择不佳,导致算法无法在有限步数内稳定。
解决方案步骤
1. 先验证分组样本量
先排查所有Country-Year组合的样本数,过滤掉样本量不足3的分组(这类分组无法完成3类聚类):
# 查看每个分组的样本量 group_counts <- df %>% count(Country, Year) print(group_counts) # 过滤样本量≥3的分组(可选,根据业务需求决定是否保留小样本) df_filtered <- df %>% group_by(Country, Year) %>% filter(n() >= 3) %>% ungroup()
2. 修正组内K-Means聚类代码
使用nest()+map()替代传统分组拆分,逻辑更清晰,同时增加迭代次数、多尝试初始中心解决收敛问题:
library(tidyverse) # 定义组内聚类函数 cluster_single_group <- function(group_data) { # 执行K-Means:增加迭代次数+多初始中心 km_model <- kmeans(group_data$Value, centers = 3, iter.max = 100, # 提高迭代次数 nstart = 20) # 多试20组初始中心,选最优结果 # 将聚类中心排序,对应Top/Middle/Bottom(按Value从高到低) center_rank <- order(km_model$centers, decreasing = TRUE) # 把聚类标签映射为指定类别 group_data$cluster <- factor(km_model$cluster, levels = center_rank, labels = c("Top", "Middle", "Bottom")) %>% as.character() return(group_data) } # 按Country-Year分组嵌套,执行聚类后展开 df_clustered <- df_filtered %>% group_by(Country, Year) %>% nest() %>% # 嵌套每个分组的数据 mutate(clustered_data = map(data, cluster_single_group)) %>% # 批量执行聚类 unnest(clustered_data) %>% # 展开嵌套数据 ungroup()
3. 小样本分组的处理建议
如果业务必须保留样本量<3的分组,可选择:
- 标记为
NA或单独类别(如"Insufficient Data") - 合并相邻年份的同国家数据(需确保业务逻辑合理)
- 改用分位数划分(单变量场景下更稳定,无需聚类):
# 分位数划分替代K-Means的方案 df_quantile <- df %>% group_by(Country, Year) %>% mutate(cluster = case_when( Value >= quantile(Value, 2/3) ~ "Top", Value <= quantile(Value, 1/3) ~ "Bottom", TRUE ~ "Middle" )) %>% ungroup()
验证逻辑正确性
运行以下代码确认每个Country-Year分组内的聚类结果符合Value高低分布:
df_clustered %>% group_by(Country, Year, cluster) %>% summarise(mean_value = mean(Value), .groups = "drop") %>% arrange(Country, Year, desc(mean_value))
内容的提问来源于stack exchange,提问作者Cristiano
相关产品推荐
相关产品推荐

