2013-05-16 2 views
9

Моя проблема очень проста: мне нужно создать список смежности из списка ребер.Как создать взвешенный список смежности/матрицу из списка ребер?

У меня есть список краев, хранящихся в документе csv с столбцом1 = node1 и column2 = node2, и я хотел бы преобразовать его в список взвешенных смежности или взвешенную матрицу смежности.

Чтобы быть более точным, то здесь, как данные выглядят как -где цифры просто узловые идентификаторы:

node1,node2 
551,548 
510,512 
548,553 
505,504 
510,512 
552,543 
512,510 
512,510 
551,548 
548,543 
543,547 
543,548 
548,543 
548,542 

Любые советы о том, как добиться преобразования из этого взвешенному списка смежности/матрицы? Вот как я решил сделать это раньше, но безуспешно (любезно Dai Shizuka):

dat=read.csv(file.choose(),header=TRUE) # choose an edgelist in .csv file format 
el=as.matrix(dat) # coerces the data into a two-column matrix format that igraph likes 
el[,1]=as.character(el[,1]) 
el[,2]=as.character(el[,2]) 
g=graph.edgelist(el,directed=FALSE) # turns the edgelist into a 'graph object' 

Спасибо!

+2

Можете ли вы предоставить нам небольшой воспроизводимый пример и ваши возможные попытки кодирования этого? –

+0

[Это сообщение] (http://stackoverflow.com/questions/14332233/using-graph-adjacency-in-r/14332667#14332667) может быть полезно. – Arun

+0

Спасибо @Arun за то, что указал мне на этот пост. Это действительно полезно, но если я не ошибаюсь, их данные уже расположены в матричной форме, тогда как, как вы можете видеть из отредактированной версии моего вопроса, у меня есть другой вклад. Редактируя сообщение, я надеюсь, что я тоже ответил Роману. – Milo

ответ

15

Этот ответ использует только базу R. Результатом является стандартная матрица, используемая для представления матрицы смежности.

el <- cbind(a=1:5, b=5:1) #edgelist (a=origin, b=destination) 
mat <- matrix(0, 5, 5) 
mat[el] <- 1 
mat 
# [,1] [,2] [,3] [,4] [,5] 
#[1,] 0 0 0 0 1 
#[2,] 0 0 0 1 0 
#[3,] 0 0 1 0 0 
#[4,] 0 1 0 0 0 
#[5,] 1 0 0 0 0 

Здесь mat ваша матрица смежности определяется из edgelist el, которая является простой cbind векторов 1:5 и 5:1.

Если ваш edgelist включает в себя весы, тогда вам нужно немного другое решение.

el <- cbind(a=1:5, b=5:1, c=c(3,1,2,1,1)) # edgelist (a=origin, b=destination, c=weight) 
mat<-matrix(0, 5, 5) 
for(i in 1:NROW(el)) mat[ el[i,1], el[i,2] ] <- el[i,3] # SEE UPDATE 
mat 
#  [,1] [,2] [,3] [,4] [,5] 
#[1,] 0 0 0 0 3 
#[2,] 0 0 0 1 0 
#[3,] 0 0 2 0 0 
#[4,] 0 1 0 0 0 
#[5,] 1 0 0 0 0 

ОБНОВЛЕНИЕ

Через некоторое время я понял, что цикл (третья линия) в предыдущем примере взвешенного edgelist не является необходимым. Вы можете заменить его следующие векторизованные операции:

mat[el[,1:2]] <- el[,3] 
14

Сообщение на моем сайте вы упоминаете в вопросе (https://sites.google.com/site/daishizuka/toolkits/sna/sna_data) использует пакет igraph, поэтому убедитесь, что загружено.

Кроме того, я недавно понял, что igraph обеспечивает гораздо более простой способ создания взвешенной матрицы смежности из edgelists, используя graph.data.frame(). Я обновил это на своем сайте, но вот простой пример:

library(igraph) 
el=matrix(c('a','b','c','d','a','d','a','b','c','d'),ncol=2,byrow=TRUE) #a sample edgelist 
g=graph.data.frame(el) 
get.adjacency(g,sparse=FALSE) 

Это должно быть сделано. Аргумент sparse = FALSE говорит ему, чтобы показать 0s в матрице смежности. Если вы действительно не хотите использовать igraph, я думаю, что это неуклюжий способ сделать это:

el=matrix(c('a','b','c','d','a','d','a','b','c','d'),ncol=2,byrow=TRUE) #a sample edgelist 
lab=names(table(el)) #extract the existing node IDs 
mat=matrix(0,nrow=length(lab),ncol=length(lab),dimnames=list(lab,lab)) #create a matrix of 0s with the node IDs as rows and columns 
for (i in 1:nrow(el)) mat[el[i,1],el[i,2]]=mat[el[i,1],el[i,2]]+1 #for each row in the edgelist, find the appropriate cell in the empty matrix and add 1. 
+0

Обратите внимание, что для взвешенной сети вам нужно добавить 'attr = 'weight'' в вызов' get.adjacency(), чтобы он возвращал взвешенную матрицу смежности вместо невзвешенной версии. –

+0

отличная ссылка, она также показывает использование фрейма для импорта списка ребер. Я не вижу эквивалентного API в Python, хотя: / – user305883

0

Другая возможность с qdapTools пакет:

library(qdapTools) 

el[rep(seq_len(nrow(el)), el[,'c']), c('a', 'b')] %>% 
    {split(.[,'b'], .[,'a'])} %>% 
    mtabulate() 

## 1 2 3 4 5 
## 1 0 0 0 0 3 
## 2 0 0 0 1 0 
## 3 0 0 2 0 0 
## 4 0 1 0 0 0 
## 5 1 0 0 0 0 
1

Начать с вашими данными каркасные ребра и использование igraph, чтобы получить матрицу смежности:

головка (ребра)

node1 node2 
1 551 548 
2 510 512 
3 548 553 
4 505 504 
5 510 512 
6 552 543 

library(igraph) 
as.matrix(get.adjacency(graph.data.frame(edges))) 

    551 510 548 505 552 512 543 553 504 547 542 
551 0 0 2 0 0 0 0 0 0 0 0 
510 0 0 0 0 0 2 0 0 0 0 0 
548 0 0 0 0 0 0 2 1 0 0 1 
505 0 0 0 0 0 0 0 0 1 0 0 
552 0 0 0 0 0 0 1 0 0 0 0 
512 0 2 0 0 0 0 0 0 0 0 0 
543 0 0 1 0 0 0 0 0 0 1 0 
553 0 0 0 0 0 0 0 0 0 0 0 
504 0 0 0 0 0 0 0 0 0 0 0 
547 0 0 0 0 0 0 0 0 0 0 0 
542 0 0 0 0 0 0 0 0 0 0 0