Учитывая однодольный объект igraph G
и матрицу смежности attrib
, содержащую атрибут ребра только для некоторых ребер в G
, какой наиболее эффективный способ добавить атрибуты в G
.
Вот воспроизводимый пример:
> set.seed(5)
> library(igraph)
> G <- erdos.renyi.game(10,.5,type = "gnp")
> as_adjacency_matrix(G) #Adjacency matrix for network
10 x 10 sparse Matrix of class "dgCMatrix"
[1,] . . . 1 1 . 1 1 1 1
[2,] . . . 1 . . . 1 . .
[3,] . . . 1 1 . 1 . 1 1
[4,] 1 1 1 . 1 1 . . 1 1
[5,] 1 . 1 1 . 1 . . . 1
[6,] . . . 1 1 . . . 1 1
[7,] 1 . 1 . . . . . 1 1
[8,] 1 1 . . . . . . . .
[9,] 1 . 1 1 . 1 1 . . .
[10,] 1 . 1 1 1 1 1 . . .
> attrib <- as_adjacency_matrix(G, sparse = FALSE)
> attrib[attrib==1] <- sample(c(0,1),sum(attrib),replace=TRUE)
> attrib #Adjacency matrix containing attributes
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 1 1 0 0 0 1 0
[2,] 0 0 0 0 0 0 0 1 0 0
[3,] 0 0 0 0 0 0 1 0 1 1
[4,] 0 1 1 0 1 1 0 0 0 0
[5,] 1 0 1 0 0 0 0 0 0 1
[6,] 0 0 0 1 0 0 0 0 1 0
[7,] 0 0 1 0 0 0 0 0 0 1
[8,] 1 0 0 0 0 0 0 0 0 0
[9,] 1 0 1 1 0 1 0 0 0 0
[10,] 1 0 0 0 0 0 1 0 0 0
Одна из возможностей — создать attrib
крайний список, а затем добавлять их один за другим в цикле. Но я думаю, что должен быть лучший вариант. Спасибо за любые идеи.
То, что вы описываете, кажется довольно запутанным, и это заставляет меня задуматься, не является ли это проблемой XY ... Если вы не знакомы с этой концепцией, я предлагаю вам проверить xyproblem.info и посмотреть, сможете ли вы улучшить вопрос на основе совет там.
Входные данные
set.seed(5)
library(igraph)
n <- 10
G <- sample_gnp(n, 0.5, directed=FALSE)
G <- simplify(G, remove.multiple = TRUE, remove.loops = TRUE)
attrib <- as_adjacency_matrix(G, sparse = FALSE)
attrib[attrib == 1] <- sample(c(0, 1),sum(attrib),replace = TRUE)
attrib #Adjacency matrix containing attributes
Решение с использованием троек (@i, @j, @x) в разреженном матричном представлении
# Using the Matrix package.
# Create sparse matrix (M).
# Create pairwise sequence of incident vertices (vp), x1, y1, x2, y2, ...
# Create a list of values (M@x)
library(Matrix)
M <- as(attrib, "TsparseMatrix")
M <- triu(as(pmax(attrib, t(attrib)), "TsparseMatrix")) # or save some space when undirected.
vp <- c(rbind(M@i, M@j)) + 1
# Convert vertex sequence to edge ids.
# Set edge attributes by edge id.
eids <- get.edge.ids(G, vp, directed=FALSE)
g2 <- set_edge_attr(G, "weight", index = eids, value=M@x)
# Show edges without weight.
E(g2)[which(is.na(E(g2)$weight))]
# + 5/23 edges from ad6a11e:
# [1] 1-- 7 4--10 5-- 6 6--10 7-- 9
g3 <- set_edge_attr(g2, name = "label", value = E(g2)$weight)
plot(g3)
Я думаю, это должно сработать для тебя
G <- G %>%
set_edge_attr("attrib", value = pmax(attrib,t(attrib))[as_edgelist(G)])
который дает
> G
IGRAPH c11c0d1 U--- 10 23 -- Erdos-Renyi (gnp) graph
+ attr: name (g/c), type (g/c), loops (g/l), p (g/n), attrib (e/n)
+ edges from c11c0d1:
[1] 1-- 4 2-- 4 3-- 4 1-- 5 3-- 5 4-- 5 4-- 6 5-- 6 1-- 7 3-- 7 1-- 8 2-- 8
[13] 1-- 9 3-- 9 4-- 9 6-- 9 7-- 9 1--10 3--10 4--10 5--10 6--10 7--10
> E(G)$attrib
[1] 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 1 1 0 1 0 1
и plot(G, edge.label = E(G)$attrib)
шоу
as_data_frame(G)
отбрасывает нижний треугольник attrib
. Это проблема, потому что attrib
не симметричен (как должно быть).
Попробуйте: pmax(t(attrib)[as_edgelist(G)], attrib[as_edgelist(G)]
. Или pmax(attrib, t(attrib))[as_edgelist(G)]
.
@clp да, это действительно хороший момент! Спасибо и смотрите мое обновление
Спасибо @ThomasIsCoding и @clp — я принял этот ответ. Пример attrib
матрицы, который я привел выше, был плохо построен и должен был быть симметричным. Принимая это во внимание и избегая необходимости в трубе, эта слегка модифицированная версия работает отлично: G <- set_edge_attr(G, "attrib", value = attrib[as_edgelist(G)])
В этом посте показано, как преобразовать матрицу в список ребер. stackoverflow.com/questions/52050505/….