跨多个变量进行配对聚类,尊重预先存在的分组变量

Pair-cluster across many variables, respecting pre-existing grouping variable

提问人:GiulioGCantone 提问时间:10/15/2023 最后编辑:GiulioGCantone 更新时间:10/21/2023 访问量:29

问:

我有一个包含列、一个分组变量和 300 个数值变量的琐碎物品。idG

我想要一种方法,将原始数据聚类到聚类中的每一行与每个分组变量中的另一行匹配/配对。 这应该是 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)
r knn 分层聚类匹配

评论


答:

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
}

您还可以通过将问题拆分为更小的部分(即在组内而不是拒绝跨组匹配)来更有效地做到这一点。