从R中的距离矩阵中找到每个索引的最短平均距离
Finding shortest mean distances per index from a distance matrix in R
第三年,我正在帮助组建一个空间 R 实验室 class,其中一项任务是确定距离最近(即平均最短距离)的特定站点一组多个其他站点。
我有一个距离矩阵 dist_m
,它是我使用 gdistance::costDistance
生成的,看起来像这样:
# Sample data
m <- matrix(c(2, 1, 8, 5,
7, 6, 3, 4,
9, 3, 2, 8,
1, 3, 7, 4),
nrow = 4,
ncol = 4,
byrow = TRUE)
# Sample distance matrix
dist_m <- dist(m)
dist_m
打印时看起来像:
1 2 3
2 8.717798
3 9.899495 5.477226
4 2.645751 7.810250 10.246951
所需输出: 从这个 dist 我希望能够识别索引值(1
、2
、3
或4
) 具有最短的平均距离。在此示例中,它将是索引 4
,其平均距离为 6.90
。理想情况下,我也希望返回平均距离 (6.90
)。
我可以通过执行以下操作找到单个索引的平均距离:
# Convert distance matrix to matrix
m = as.matrix(dist_m)
# Set diagonals and upper triangle to NA
m[upper.tri(m)] = NA
m[m == 0] = NA
# Calculate mean for index
mean(c(m[4,], m[,4]), na.rm = TRUE)
但是,我理想的解决方案是直接识别具有最小平均距离的索引,而不是必须手动插入索引值(实际数据集将比这大得多)。
由于这是针对大学的 class,我希望任何解决方案都尽可能简单:for 循环和 apply 函数对于没有 R 经验的学生来说可能很难掌握.
试试这个:
rMeans <- rowMeans(m, na.rm = T)
names(rMeans) <- NULL
which(rMeans == min(rMeans, na.rm = T))
# [1] 4
或作为函数:
minMeanDist <- function(x) {
m <- as.matrix(x)
m[upper.tri(m)] <- NA
m[m == 0] <- NA
rMeans <- rowMeans(m, na.rm = T)
names(rMeans) <- NULL
mmd <- min(rMeans, na.rm = T)
ind <- which(rMeans == mmd)
list(index = ind, min_mean_dist = mmd)
}
minMeanDist(dist_m)
# $index
# [1] 4
#
# $min_mean_dist
# [1] 6.900984
如果您想使用 tidyverse
这是一种方法:
as.matrix(dist_m) %>%
as.tibble() %>%
rownames_to_column(var = "start_node") %>%
gather(end_node, dist, -start_node) %>% # go long
filter(dist != 0) %>% # drop identity diagonal
group_by(start_node) %>% # now summarise
summarise(mean_dist = mean(dist)) %>%
filter(mean_dist == min(mean_dist)) # chose minimum mean_dist
# A tibble: 1 x 2
start_node mean_dist
<chr> <dbl>
1 4 6.900984
它有点长,但是通过管道可以很容易地看到每一行发生了什么,并且你会得到一个很好的输出。
第三年,我正在帮助组建一个空间 R 实验室 class,其中一项任务是确定距离最近(即平均最短距离)的特定站点一组多个其他站点。
我有一个距离矩阵 dist_m
,它是我使用 gdistance::costDistance
生成的,看起来像这样:
# Sample data
m <- matrix(c(2, 1, 8, 5,
7, 6, 3, 4,
9, 3, 2, 8,
1, 3, 7, 4),
nrow = 4,
ncol = 4,
byrow = TRUE)
# Sample distance matrix
dist_m <- dist(m)
dist_m
打印时看起来像:
1 2 3
2 8.717798
3 9.899495 5.477226
4 2.645751 7.810250 10.246951
所需输出: 从这个 dist 我希望能够识别索引值(1
、2
、3
或4
) 具有最短的平均距离。在此示例中,它将是索引 4
,其平均距离为 6.90
。理想情况下,我也希望返回平均距离 (6.90
)。
我可以通过执行以下操作找到单个索引的平均距离:
# Convert distance matrix to matrix
m = as.matrix(dist_m)
# Set diagonals and upper triangle to NA
m[upper.tri(m)] = NA
m[m == 0] = NA
# Calculate mean for index
mean(c(m[4,], m[,4]), na.rm = TRUE)
但是,我理想的解决方案是直接识别具有最小平均距离的索引,而不是必须手动插入索引值(实际数据集将比这大得多)。
由于这是针对大学的 class,我希望任何解决方案都尽可能简单:for 循环和 apply 函数对于没有 R 经验的学生来说可能很难掌握.
试试这个:
rMeans <- rowMeans(m, na.rm = T)
names(rMeans) <- NULL
which(rMeans == min(rMeans, na.rm = T))
# [1] 4
或作为函数:
minMeanDist <- function(x) {
m <- as.matrix(x)
m[upper.tri(m)] <- NA
m[m == 0] <- NA
rMeans <- rowMeans(m, na.rm = T)
names(rMeans) <- NULL
mmd <- min(rMeans, na.rm = T)
ind <- which(rMeans == mmd)
list(index = ind, min_mean_dist = mmd)
}
minMeanDist(dist_m)
# $index
# [1] 4
#
# $min_mean_dist
# [1] 6.900984
如果您想使用 tidyverse
这是一种方法:
as.matrix(dist_m) %>%
as.tibble() %>%
rownames_to_column(var = "start_node") %>%
gather(end_node, dist, -start_node) %>% # go long
filter(dist != 0) %>% # drop identity diagonal
group_by(start_node) %>% # now summarise
summarise(mean_dist = mean(dist)) %>%
filter(mean_dist == min(mean_dist)) # chose minimum mean_dist
# A tibble: 1 x 2
start_node mean_dist
<chr> <dbl>
1 4 6.900984
它有点长,但是通过管道可以很容易地看到每一行发生了什么,并且你会得到一个很好的输出。