You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言中如何移除距离矩阵/对称矩阵及层次聚类中的异常值?

解答你的两个聚类异常值处理问题

我来帮你一步步解决这两个关于异常值处理的问题:


一、距离/对称矩阵中查找并移除异常值

针对距离矩阵或对称矩阵的异常值检测,核心思路是基于样本间的相对距离识别离群点,这里分享两种实用方法:

方法1:基于平均距离的IQR法

异常样本通常和其他所有样本的平均距离远大于大部分样本,我们可以用四分位距(IQR)划定正常范围,超出范围的视为异常值:

# 假设你的距离矩阵是dist对象d,先转换为矩阵格式
d_matrix <- as.matrix(d)

# 计算每个样本到其他所有样本的平均距离
avg_dist <- rowMeans(d_matrix)

# 用IQR计算异常值阈值
q1 <- quantile(avg_dist, 0.25)
q3 <- quantile(avg_dist, 0.75)
iqr_range <- q3 - q1
upper_cutoff <- q3 + 1.5 * iqr_range  # 常用1.5倍IQR作为边界

# 找出平均距离超出上限的异常样本索引
outlier_idx <- which(avg_dist > upper_cutoff)

# 从距离矩阵中移除异常值(同时删除对应的行和列)
d_clean <- d[-outlier_idx, -outlier_idx]

方法2:局部离群因子(LOF)算法

LOF会计算每个样本的局部密度,若某样本的密度远低于其邻居,就会被标记为异常值,适合复杂分布的数据:

library(dbscan)

# 用预处理后的原始数据计算LOF值(k取5-10都可以,代表参考的邻居数量)
lof_scores <- lof(engmale161, k = 5)

# 设定阈值(通常LOF>2就可视为异常值,可根据数据调整)
outlier_idx <- which(lof_scores > 2)

# 移除异常值后重新生成距离矩阵
engmale161_clean <- engmale161[-outlier_idx, ]
d_clean <- dist(engmale161_clean, method = "euclidean")

二、移除层次聚类中识别出的单样本异常值

你已经通过聚类结果发现了ID为4165634865的单样本异常值,直接从原始数据中移除后重新执行聚类流程即可:

# 找到异常样本在原始数据中的行索引(根据行名匹配)
outlier_idx <- which(rownames(engmale161) == "4165634865")

# 从原始数据中移除该异常样本
engmale161_clean <- engmale161[-outlier_idx, ]

# 重新执行你的预处理和聚类流程
engmale161_clean <- na.omit(engmale161_clean)
engmale161_clean <- scale(engmale161_clean)
d_clean <- dist(engmale161_clean, method = "euclidean")
hc1_clean <- hclust(d_clean, method = "average")

# 重新切割聚类(你之前已确定最优k=4,直接使用即可)
sub_grp_clean <- cutree(hc1_clean, k = 4)
table(sub_grp_clean)

# 可视化验证聚类结果
fviz_cluster(list(data = engmale161_clean, cluster = sub_grp_clean), geom = "point")

补充建议:

如果后续经常遇到这类单样本聚类的情况,建议在聚类前先做异常值检测(用上面提到的IQR或LOF方法),提前过滤离群点,避免聚类结果出现极端的单样本簇。


内容的提问来源于stack exchange,提问作者김태환

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:00:34