【发布时间】:2022-07-13 05:32:56
【问题描述】:
我有一个图表,每个节点都有一个值(红色值)。
我想做以下两件事(我猜1是2的特例):
-
应该为每个节点分配指向它的直接对等节点的平均值。例如节点 #5
(1+2)/2=1.5或节点 #3(0+2+0)/3=2/3。 -
而不是直接邻居,包括所有连接的节点,但扩散时间为 1/n,其中 n 是到节点的距离。信息越远,我们所拥有的信号就越弱。
我查看了 igraph 的功能,但找不到任何这样做的东西(不过我可能已经监督了)。我怎么能做这个计算?
以下是具有随机值的示例网络的代码。
library(tidyverse)
library(tidygraph)
library(ggraph)
set.seed(6)
q <- tidygraph::play_erdos_renyi(6, p = 0.2) %>%
mutate(id = row_number(),
value = sample(0:3, size = 6, replace = T))
q %>%
ggraph(layout = "with_fr") +
geom_edge_link(arrow = arrow(length = unit(0.2, "inches"),
type = "closed")) +
geom_node_label(aes(label = id)) +
geom_node_text(aes(label = value), color = "red", size = 7,
nudge_x = 0.2, nudge_y = 0.2)
编辑,找到解决方案1
q %>%
mutate(value_smooth = map_local_dbl(order = 1, mindist = 1, mode = "in",
.f = function(neighborhood, ...) {
mean(as_tibble(neighborhood, active = 'nodes')$value)
}))
编辑 2,解决 2,我猜不是最优雅的
q %>%
mutate(value_smooth = map_local_dbl(order = 1, mindist = 0, mode = "in",
.f = function(neighborhood, node, ...) {
ne <- neighborhood
ne <- ne %>%
mutate(d = node_distance_to(which(as_tibble(ne,
active = "nodes")$id == node)))
as_tibble(ne, active = 'nodes') %>%
filter(d != 0) %>%
mutate(helper = value/d) %>%
summarise(m = mean(value)) %>%
pull(m)
}))
Edit 3,map_local_dbl 的更快替代方案
map_local 循环遍历图的所有节点。对于大图,这需要很长时间。对于仅计算均值,这不是必需的。一个更快的替代方法是使用邻接矩阵和一些矩阵乘法。
q_adj <- q %>%
igraph::as_adjacency_matrix()
# out
(q_adj %*% as_tibble(q)$value) / Matrix::rowSums(q_adj)
# in
(t(q_adj) %*% as_tibble(q)$value) / Matrix::colSums(q_adj)
邻接矩阵的平方是二阶邻接矩阵,以此类推。因此,也可以创建问题 2 的解决方案。
编辑 4,直接加权平均
假设原始图的每条边都有权重。
q <- q %>%
activate(edges) %>%
mutate(w = c(1,0.5,1,0.5,1,0.5,1)) %>%
activate(nodes)
我们想计算直接同行价值的加权平均值。
q_adj_wgt <- q %>%
igraph::as_adjacency_matrix(attr = "w")
# out
(q_adj_wgt %*% as_tibble(q)$value) / Matrix::rowSums(q_adj_wgt)
# in
(t(q_adj_wgt) %*% as_tibble(q)$value) / Matrix::colSums(q_adj_wgt)
【问题讨论】:
标签: r graph-theory igraph tidygraph