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

问题描述 投票:0回答:1

我有一个带有

id
列、
G
分组变量和 300 个数字变量的 tibble。

我想要一种方法,将原始数据聚类到每行与每个分组变量中的另一行在集群中匹配/配对的程度。 这应该是一个 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 cluster-analysis knn hierarchical-clustering matchit
1个回答
0
投票

这称为非二分匹配。

nbpMatching
包实现了它。

你也可以自己做一个贪婪的版本,首先寻找距离最近的对。首先,创建一个 NxN 距离矩阵,然后找到最接近的一对并记录下来。否认这些单位在未来配对的能力。重复直到所有单位都匹配。这是一些使用马哈拉诺比斯距离执行此操作的代码。

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
}

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

© www.soinside.com 2019 - 2024. All rights reserved.