提问人:GiulioGCantone 提问时间:10/15/2023 最后编辑:GiulioGCantone 更新时间:10/21/2023 访问量:29
跨多个变量进行配对聚类,尊重预先存在的分组变量
Pair-cluster across many variables, respecting pre-existing grouping variable
问:
我有一个包含列、一个分组变量和 300 个数值变量的琐碎物品。id
G
我想要一种方法,将原始数据聚类到聚类中的每一行与每个分组变量中的另一行匹配/配对。 这应该是 1kNN。奇数组中的备用原始数据可以排除在群集之外。
因此,如果一个组中有 4 个原始数据,那么将有 2 个 2 个聚类。如果有 5 个原始数据,则 2 个 2 个簇和一个备用原始数据。
我想我喜欢用于聚类的马氏距离,但我对另一种建议持开放态度。
我认为簇内马氏症的诊断变量也可能有所帮助。
从技术上讲,它做了一些非常相似的事情,对原始数据过度施加了二元分类。我不希望需要这样的分类。MatchIt
例:
tibble(
id = c(1:8),
g = rep(c("A","B"),4),
v1 = rnorm(8),
v2 = rnorm(8),
v3 = rnorm(8)
) -> obs
理想的样子
obs %>%
mutate(cluster = sample(c(1:2),replace = F) %>% rep(2),
.by = g) %>%
mutate(pair = str_c(g,cluster)) %>%
arrange(pair)
答:
1赞
Noah
10/21/2023
#1
这称为非二分匹配。nbpMatching
包实现它。
你也可以自己做一个贪婪的版本,它首先寻找距离最近的对。首先,创建一个 NxN 距离矩阵,然后找到最接近的对并记录下来。拒绝这些单位在未来成对的能力。重复上述步骤,直到所有单位都匹配。下面是一些使用 Mahalanobis 距离执行此操作的代码。
obs$pair <- NA
#Create distance matrix of variables
d <- MatchIt::mahalanobis_dist(~v1 + v2 + v3, data = obs)
#Deny matches that belong to different clusters
d[!outer(obs$g, obs$g, "==")] <- Inf
#Deny self-matching
diag(d) <- Inf
k <- 1
repeat {
min_pos <- arrayInd(which.min(d), dim(d))
if (!is.finite(d[min_pos])) break
obs$pair[drop(min_pos)] <- k
d[drop(min_pos),] <- Inf
d[,drop(min_pos)] <- Inf
k <- k + 1
}
您还可以通过将问题拆分为更小的部分(即在组内而不是拒绝跨组匹配)来更有效地做到这一点。
评论