您不应该删除 NA 值,它们在计算距离时会有所帮助。
所以从你的原始数据开始:
df
V1 V2 V3 V4 V5
1 1 7 9 4 NA
2 3 6 NA NA NA
3 1 6 6 4 3
4 7 7 NA NA NA
5 4 3 1 8 NA
我们尝试一次性使用dist() 计算所有行之间的距离:
dst <- as.matrix(dist(df, diag=TRUE, upper=TRUE))
dst
1 2 3 4 5
1 0.000000 3.535534 3.535534 9.486833 11.456439
2 3.535534 0.000000 3.162278 6.519202 5.000000
3 3.535534 3.162278 0.000000 9.617692 8.587782
4 9.486833 6.519202 9.617692 0.000000 7.905694
5 11.456439 5.000000 8.587782 7.905694 0.000000
现在这些值有点奇怪,不确定这是否是您要寻找的。阅读help(dist)我们看到了这一点:
如果某些列
在计算欧几里得、曼哈顿、堪培拉或
Minkowski 距离,总和按比例放大
使用的列数。如果所有对都被排除在
计算一个特定的距离,值为'NA'。
这就是说 - 如果您的数据有 NA,距离会按比例缩放,因此缺失值也会添加到距离中。这使得距离在大小上具有可比性,尽管某些元素具有 NA 值。
现在,如果您不希望这样,我们必须重新调整这些距离,以便它们不会被缩放。但首先我们需要了解它们是如何缩放的。
该函数看到,对于某些特定距离,使用了 5 列中的 2 列,而其他列不适用。它的作用是将距离内的总和乘以 5/2,然后取平方根值(根据欧几里得公式)。
所以我们需要做的是第 1 步 - 获得这些比率,第 2 步 - 取这些比率的平方根值,第 3 步 - 重新调整。
对于每个距离,我们首先获取用于计算它们的 NA 元素的数量:
nas <- outer(rowSums(is.na(df)), rowSums(is.na(df)), FUN=pmax)
nas
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 1 3 1
[2,] 3 3 3 3 3
[3,] 1 3 0 3 1
[4,] 3 3 3 3 3
[5,] 1 3 1 3 1
现在使用它,我们得到每个距离具有 NA 值的数据部分:
frac <- (ncol(df)-nas) / ncol(df)
frac
[,1] [,2] [,3] [,4] [,5]
[1,] 0.8 0.4 0.8 0.4 0.8
[2,] 0.4 0.4 0.4 0.4 0.4
[3,] 0.8 0.4 1.0 0.4 0.8
[4,] 0.4 0.4 0.4 0.4 0.4
[5,] 0.8 0.4 0.8 0.4 0.8
例如,我们看到,对于第 1-2 对,我们有 3 个缺失值和 2 个可用值。所以可用的占整体的40%。
接下来,我们取这些比率的平方根,并将它们乘以我们得到的距离(那些调整后的距离),以恢复这种缩放:
res <- dst * sqrt(frac)
res
1 2 3 4 5
1 0.000000 2.236068 3.162278 6.000000 10.246951
2 2.236068 0.000000 2.000000 4.123106 3.162278
3 3.162278 2.000000 0.000000 6.082763 7.681146
4 6.000000 4.123106 6.082763 0.000000 5.000000
5 10.246951 3.162278 7.681146 5.000000 0.000000
这就是你的结果。所以总结一下:
dst <- as.matrix(dist(df, diag=TRUE, upper=TRUE))
nas <- outer(rowSums(is.na(df)), rowSums(is.na(df)), FUN=pmax)
frac <- (ncol(df)-nas) / ncol(df)
res <- dst * sqrt(frac)