2013-05-16 21 views
9

Il mio problema è molto semplice: ho bisogno di creare una lista/matrice di adiacenza da un elenco di spigoli.Come creare una lista/matrice di adiacenza ponderata dall'elenco di spigoli?

Ho un elenco di bordi memorizzato in un documento csv con column1 = node1 e column2 = node2 e vorrei convertirlo in una lista di adiacenza ponderata o in una matrice di adiacenza ponderata.

Per essere più precisi, ecco come i dati si presenta come -dove i numeri sono ids semplicemente nodi:

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 

Eventuali suggerimenti su come ottenere la conversione da questo ad una lista di adiacenza/matrice ponderata? Ecco come ho deciso di farlo in precedenza, senza successo (per gentile concessione di 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' 

Grazie!

+2

Puoi fornirci un piccolo esempio riproducibile e i tuoi possibili tentativi di codifica? –

+0

[questo post] (http://stackoverflow.com/questions/14332233/using-graph-adjacency-in-r/14332667#14332667) potrebbe essere utile. – Arun

+0

Grazie a @Arun per avermi indirizzato a quel post. È davvero utile, ma se non sbaglio i loro dati sono già disposti in modo matriciale mentre, come potete vedere dalla versione modificata della mia domanda, ho un input diverso. Modificando il post, spero di aver risposto anche a Roman. – Milo

risposta

15

Questa risposta utilizza solo la base R. Il risultato è una matrice standard utilizzata per rappresentare la matrice di adiacenza.

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 

Qui mat è la vostra matrice di adiacenza definito da edgelist el, che è un semplice cbind dei vettori 1:5 e 5:1.

Se l'edgelist include pesi, è necessaria una soluzione leggermente diversa.

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 

UPDATE

Qualche tempo dopo ho capito che il ciclo (3a linea) nel precedente esempio edgelist pesata è superflua. È possibile sostituirlo con il seguente operazione vettorizzati:

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

Il post sul mio sito si parla nella questione (https://sites.google.com/site/daishizuka/toolkits/sna/sna_data) utilizza il pacchetto IGRAPH, in modo da assicurarsi che viene caricato.

Inoltre, di recente ho capito che igraph fornisce un modo molto semplice per creare una matrice di adiacenza ponderata da edgelists, utilizzando graph.data.frame(). Ho aggiornato questo sul mio sito, ma ecco un semplice esempio:

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) 

Che dovrebbe farlo. L'argomento sparse = FALSE dice di mostrare gli 0 nella matrice di adiacenza. Se davvero non si vuole utilizzare IGRAPH, credo che questo sia un modo goffo di farlo:

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

Si noti che per una rete ponderata, si vorrà aggiungere un 'attr = 'peso'' alla chiamata' get.adjacency() 'per fare in modo che restituisca una matrice di adiacenza ponderata invece di una versione non ponderata. –

+0

ottimo link, mostra anche l'uso del frame per importare l'elenco dei bordi. Non vedo API equivalente in Python: / – user305883

0

Un'altra possibilità con i qdapTools pacchetto:

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

Inizia con i tuoi dati bordi delle cornici e uso IGRAPH per ottenere matrice di adiacenza:

testa (bordi)

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 
Problemi correlati