我有一个从mongo数据库导入的元素数据框,示例:
# | Mcg | Gvh | Alm | Mit | Vac | Nuc
:----: | :----: | :----: | :----: | :----: | :----: | :----:
1 | 0.62 | 0.42 | 0.47 | 0.16 | 0.52 | 0.22
2 | 0.60 | 0.40 | 0.52 | 0.46 | 0.53 | 0.22
3 | 0.47 | 0.32 | 0.64 | 0.30 | 0.63 | 0.22
4 | 0.46 | 0.39 | 0.54 | 0.22 | 0.48 | 0.25
5 | 0.50 | 0.46 | 0.52 | 0.16 | 0.52 | 0.26
data = data.frame(
Mcg = c(0.62, 0.60, 0.47, 0.46, 0.50),
Gvh = c(0.42, 0.40, 0.32, 0.39, 0.46),
Alm = c(0.47, 0.52, 0.64, 0.54, 0.52),
Mit = c(0.16, 0.46, 0.30, 0.22, 0.16),
Vac = c(0.52, 0.53, 0.63, 0.48, 0.52),
Nuc = c(0.22, 0.22, 0.22, 0.25, 0.26),
row.names = c(1:5)
)
我需要根据距离矩阵计算每对示例的共享最近邻居的数量,如果该值高于给定的阈值,请将这些示例索引保存在名为clusters的列表中。
# | 1 | 2 | 3 | 4 | 5
:----: | :----: | :----: | :----: | :----: | :----:
1 | 0.00 | 0.31 | 0.31 | 0.19 | 0.14
2 | 0.31 | 0.00 | 0.27 | 0.28 | 0.32
3 | 0.31 | 0.27 | 0.00 | 0.21 | 0.26
4 | 0.19 | 0.28 | 0.21 | 0.00 | 0.11
5 | 0.14 | 0.32 | 0.26 | 0.11 | 0.00
dists = as.matrix(
dist(data, method = "euclidean", diag = FALSE, upper = FALSE, p = 2)
)
我已经有一个带'for'循环的工作代码:
# get indexes of k nearest neighbors
Neighbors <- function(id, k) {
as.integer( names( sort( dists[id, -id] )[1:k] ) )
}
threshold = 5
k = 10
clusters = vector("list", (k - threshold))
for (y in 1:(nrow(data) - 1)) {
neighbors.e1 = Neighbors(y, k)
for (z in (y+1):(nrow(data))) {
neighbors.e2 = Neighbors(z, k)
snn = sum(table(c(neighbors.e1, neighbors.e2)) == 2)
if (snn > threshold) {
cluster.id = snn - threshold
if (!(y %in% clusters[[cluster.id]])) {
clusters[[cluster.id]] = c(clusters[[cluster.id]], y)
}
if (!(z %in% clusters[[cluster.id]])) {
clusters[[cluster.id]] = c(clusters[[cluster.id]], z)
}
}
}
}
此解决方案非常慢。因此,我想通过使用apply函数而不是循环来优化它。
以下是完整数据集(1484行)的“群集”列表
> clusters
[[1]]
[1] 1 3 6 7 19 2 23 8 16 17 18 20 4 5 14 21 24 15 9 10 12 22 11 13
[[2]]
[1] 1 17 24 2 3 7 8 16 18 20 6 4 10 12 13 22 5 19 21 23 9 15 11 14
[[3]]
[1] 4 11 7 16 19 8 18 10 12 13 14 22 20 17 24
[[4]]
[1] 5 21 7 8 18 20
[[5]]
NULL