[英]multiplicative distance between graph nodes
我想找到圖中所有節點之間的距離,而不是總和我想要乘以它們的邊權重。
舉個例子:
library(igraph)
# create a weighted adjacency matrix
mx <- structure(c(0, 0.5, 0, 0, 0, 0.5, 0, 0.5, 0.5, 0, 0, 0.5, 0, 0, 0.5, 0, 0.5,
0, 0, 0, 0, 0, 0.5, 0, 0), .Dim = c(5L, 5L))
## convert to igraph object
mx2 <- graph.adjacency(mx, weighted = TRUE)
我可以得到所有節點之間的距離如下:
shortest.paths(mx2)
[,1] [,2] [,3] [,4] [,5]
[1,] 0.0 0.5 1.0 1.0 1.5
[2,] 0.5 0.0 0.5 0.5 1.0
[3,] 1.0 0.5 0.0 1.0 0.5
[4,] 1.0 0.5 1.0 0.0 1.5
[5,] 1.5 1.0 0.5 1.5 0.0
但是這會計算所有節點之間的距離,方法是將我想要乘以它們的相關權重相加,這將產生以下結果:
[,1] [,2] [,3] [,4] [,5]
[1,] 0.000 0.50 0.25 0.250 0.125
[2,] 0.500 0.00 0.50 0.500 0.250
[3,] 0.250 0.50 0.00 0.250 0.500
[4,] 0.250 0.50 0.25 0.000 0.125
[5,] 0.125 0.25 0.50 0.125 0.000
據我所知,使用igraph中的“開箱即用”選項無法做到這一點,我正在努力自己解決這個問題(在實際數據中,矩陣更大,各種尺寸)。 任何建議將不勝感激。
這是一個提案。 可能還有很大的改進空間,但它可以提供預期的產量。 我們的想法是為每對節點提取最短路徑,然后乘以與每條路徑相關的權重(我使用了這個答案中的一些代碼)。
shortest.paths.multi <- function(mx) {
output <- mx
mx2 <- graph.adjacency(mx, weighted = TRUE)
for (r in 1:nrow(mx)){
for (c in 1:nrow(mx)){
SP <- shortest_paths(mx2, from = r, to = c)
VP <- SP$vpath[[1]]
EP <- rep(VP, each=2)[-1]
EP <- EP[-length(EP)]
output[r, c] <- prod(E(mx2)$weight[get.edge.ids(mx2, EP)])
}
}
diag(output) <- 0
output
}
shortest.paths.multi(mx)
[,1] [,2] [,3] [,4] [,5] [1,] 0.000 0.50 0.25 0.250 0.125 [2,] 0.500 0.00 0.50 0.500 0.250 [3,] 0.250 0.50 0.00 0.250 0.500 [4,] 0.250 0.50 0.25 0.000 0.125 [5,] 0.125 0.25 0.50 0.125 0.000
編輯
這可能是編寫此函數的更好方法:
shortest.paths.multi <- function(r, c){
SP <- shortest_paths(mx2, from = r, to = c)
VP <- SP$vpath[[1]]
EP <- rep(VP, each=2)[-1]
EP <- EP[-length(EP)]
prod(E(mx2)$weight[get.edge.ids(mx2, EP)])
}
VecFun <- Vectorize(shortest.paths.multi)
output <- outer(1:nrow(mx), 1:ncol(mx), FUN = VecFun)
diag(output) <- 0
output
在上面的答案中寫一個函數肯定是更好的方法。 但另一種思考問題的方法是,如果你想要權重的產品,而shortest.paths()
給你權重的總和,那么如果你輸入shortest.paths()
函數你的權重的對數,指數結果將等於權重的乘積。
這在實踐中比我想象的要有點挑剔,因為你的權重在0和1之間,而shortest.paths shortest.paths()
算法不接受負權重,但是你可以通過在前后乘以-1來解決這個問題。計算權重。
library(igraph)
## Cheat and log it
ln.mx <- structure(c(0, 0.5, 0, 0, 0, 0.5, 0, 0.5, 0.5, 0, 0, 0.5, 0, 0, 0.5, 0, 0.5,
0, 0, 0, 0, 0, 0.5, 0, 0), .Dim = c(5L, 5L))
ln.mx <- ifelse(ln.mx!=0, log(ln.mx), 0)
## convert to igraph object
ln.mx2 <- graph.adjacency(ln.mx, weighted = TRUE)
# The issue with the approach is that the shortest.path algorithm doesn't like
# negative weights. Since your weights fall in (0,1) their log is negative.
# We multiply edge weights by -1 to swap the sign, and then will
# multiply again by -1 to get
# the result
E(ln.mx2)$weight <- -1*E(ln.mx2)$weight
# The result is just the regular shortest paths algorithm,
# times -1 (to undo the step above) and exponentiated to undue the logging
res <- exp(shortest.paths(ln.mx2)* -1)
# its still not perfect since the diagonal distance defaults to
# zero and exp(0) is 1, not 0. So we manually reset the diagonal
diag(res) <- 0
# The result is as hoped
res
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.000 0.50 0.25 0.250 0.125
#> [2,] 0.500 0.00 0.50 0.500 0.250
#> [3,] 0.250 0.50 0.00 0.250 0.500
#> [4,] 0.250 0.50 0.25 0.000 0.125
#> [5,] 0.125 0.25 0.50 0.125 0.000
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.