Сумма весов по атрибутам вершин - PullRequest
0 голосов
/ 28 июня 2018

В R у меня есть взвешенный неориентированный граф в качестве объекта igraph:

IGRAPH 60a5b9d UNW- 2777 19103 -- 
+ attr: name (v/c), label (v/c), nom (v/c), sigle (v/c), statut (v/c), champ (v/c), cp (v/c), info (v/c),
+ edges from 60a5b9d (vertex names):
[1] 0--35   1--9    1--199  1--484  2--171  2--483  2--978  2--3564 3--9    3--1464 3--1474 3--2981 4--75   6--18   6--25  
[16] 6--28   6--33   6--64   6--65   6--71   6--86   6--87   6--101  6--104  6--113  6--118  6--144  6--166  6--182  6--183 
+ ... omitted several edges

То, что я пытаюсь сделать, - это самым элегантным и простым способом суммировать веса ребер от одного типа вершины к другому и добавить результат в качестве атрибута вершины.

Другими словами, я не уверен, как я могу, для каждой вершины, которая соответствует V(net)$attribute == "value", перечислить все ребра в вершины, которые соответствуют V(net)$attribute == "value2", а затем суммировать веса. И я не знаю, является ли igraph лучшим вариантом для выполнения таких операций, или мне следует работать с фреймом данных края и фреймом данных вершины.

Ответы [ 3 ]

0 голосов
/ 29 июня 2018

Так как я не знал, как это сделать с igraph, я сделал это с фреймами данных и dplyr. Вот мой код, если он может помочь кому-то еще в какой-то момент:

# transform igraph object in two data frames and remove NAs
res_df <- igraph::as_data_frame(res, 'both')
res_v <- res_df$vertices
res_e <- res_df$edges
res_v[is.na(res_v)] <- 0
res_e[is.na(res_e)] <- 0

# generate two vectors listing ids of the nodes following critera 1 and criteria 2
crit1_id <- res_v %>% filter(criteria == "value1") %>% .$name %>% as.numeric()
crit2_id <- res_v %>% filter(criteria == "value2") %>% .$name %>% as.numeric()

# generate an edge list listing ties between any id from crit1_id to any id from crit2_id
list_edge_1 <- res_e %>% filter(from %in% crit1_id & to %in% crit2_id)
list_edge_2 <- res_e %>% filter(from %in% crit2_id & to %in% crit1_id)
list_edge <- rbind(list_edge_1, list_edge_2)

# for each node in crit1_id, list direct edges to any node in crit2_id and store the weights in a vector, then add the sum of weights as a node attribute
for (n in crit1_id) {
   s <- list_edge %>% filter(from == n | to == n) %>% .$weight
   res_v$new_attribute[res_v$name == n] <- sum(s)
}

# make a new igraph object if you need
new_res <- graph_from_data_frame(res_e,
                         directed = F,
                         vertices = res_v)
0 голосов
/ 29 июня 2018

Вы действительно можете сделать это с igraph, пожалуйста, обратитесь к комментариям в этом коде:

library(igraph)

# sample
net <- make_empty_graph(3L, FALSE) %>%
  set_vertex_attr(name = "myattr", value = c("a", "b", "b")) %>%
  add_edges(c(1L, 2L), weight = 10)

vertices <- V(net)
a_vertices <- which(vertices$myattr == "a")
b_vertices <- which(vertices$myattr == "b")

# each column of edge_list will have a potential pair of nodes
edge_list <- t(as.matrix(expand.grid(a_vertices, b_vertices)))
# this will get the edge ID corresponding to each pair
edges <- get.edge.ids(net, edge_list)
# if the edge does not exist, its ID will be 0
edges <- edges[edges != 0L]

# the sum of weights from all existing edges that fulfill the condition
total <- sum(edge_attr(net, "weight", edges))
0 голосов
/ 28 июня 2018

Я думаю, что функция distances и ее кузены - это то, что вы ищете. Замечу, что я не уверен, что `расстояния с возвратом, если есть несколько путей между двумя узлами

Маленький MWE:

library(igraph)

g <- barabasi.game(10, directed = FALSE)
E(g)$weight <- runif(ecount(g), min = 1,max = 5)
plot(g, edge.width=E(g)$weight)

distances(g, V(g)[1], V(g)[c(3,5,8)])
# [,1]     [,2]     [,3]
# [1,] 3.78849 6.174016 5.652662

sum(distances(g, V(g)[1], V(g)[c(3,5,8)]))
# [1] 15.61517
...