Re: [R] For Social Network Analysis-Graph Analysis - How to convert 2 mode data to 1 mode data?

From: Messing, Solomon O. <SOLOMON.O.MESSING_at_saic.com>
Date: Sat, 17 May 2008 09:32:27 -0400

Consider the following two mode-data:  

edgelist:
  actor event

1   Sam     a
2   Sam     b
3   Sam     c
4  Greg     a
5   Tom     b
6   Tom     c
7   Tom     d
8  Mary     b
9  Mary     d
 
Two-Mode Adjacency Matrix:
     a b c d

Sam 1 1 1 0
Greg 1 0 0 0
Tom 0 1 1 1
Mary 0 1 0 1  

To transform two mode to one mode data, we need a function that transforms the data like so:  

Sam is connected to Greg (via event a)
Sam is connected to Tom (via event b and c) Sam is connected to Mary (via event b)
Tom is connected to Mary (via event b and d)  

OK, now I load my data by executing the following:

###################################################################################
require(igraph)
df <- data.frame(actor = c('Sam','Sam','Sam','Greg','Tom','Tom','Tom','Mary','Mary'),
                  event =c('a','b','c','a','b','c','d','b','d') ) 
g = graph.data.frame(df, directed=F) #Coerce data to igraph object 'g'

#Loading Function two.to.one:
##two.to.one() transforms 2-mode data to 1-mode two.to.one <- function(g, keep) {

 neis <- neighborhood(g, order=2)
 neis <- lapply(seq(neis), function(x) neis[[x]][ neis[[x]] != x-1]) ## drop self-loops
 neis <- lapply(neis, function(x) x[ x %in% keep ])                  ## keep only these
 neis <- lapply(seq(neis), function(x) t(cbind(x-1, neis[[x]])))     ## create edge lists
 neis[-keep-1] <- NULL                                               ## these are not needed
 neis <- matrix(unlist(neis), byrow=TRUE, nc=2)                      ## a single edge list
 neis <- neis[ neis[,1] > neis[,2], ]                                ## count an edge once only
 mode(neis) <- "character"
 g2 <- graph.edgelist(neis, dir=FALSE)
 V(g2)$id <- V(g2)$name ## 'id' is used in Pajek  g2
}

#Actors are the first 4 verticies, set them to be kept: keep = V(g)[1:4]
#Convert matrix with two.to.one:
g2 = two.to.one(g, keep)
g2

###################################################################################
This yields the following output:
> g2

Vertices: 4
Edges: 2
Directed: FALSE
Edges:           

[0] 3 -- 2
[1] 4 -- 1

But, this can't be right. Here there are only two edges where there should be four, and if I am inturpreting correctly, the output it is reporting that Tom is connected to Greg (he is not) and Sam is connected to Mary (which is true).

When I load my function, which is designed to transform a two mode edgelist (e.g. two columns of data) into a one-mode adjacency matrix it seems to work:

###################################################################################
#load my function
df.to.nxn <- function( x, y ){                                                     # x values will be the N x N values   
    M <- matrix( nrow = length( unique( x ) ), ncol = length( unique( x ) ), 
          dimnames = list( unique( x ), unique( x ) ) )
    M[ 1:length( unique( x ) ), 1:length( unique( x ) ) ] <- 0                    #initialize the values to 0 - this possibly could be removed for illustrative purposes    
    for( i in 1:length( x ) ) {                                                   # iterate through rows of data    
            index = which( y == y[i] )                    
                M[ as.character( x[ index ] ), as.character( x[ index ] ) ] = 1        
     }
M                                                                                 # return M, an N x N matrix
}
#Convert matrix
g3 = df.to.nxn(df$actor, df$event)
g4 = graph.adjacency(g3, mode = "undirected", diag = F) V(g4)$name = row.names(g3)
g4
###################################################################################
This yields:
> g4

Vertices: 4
Edges: 4
Directed: FALSE
Edges:                 
[0] Sam  -- Greg
[1] Sam  -- Tom 
[2] Sam  -- Mary
[3] Tom  -- Mary

Which is what we wanted. I have not figured out how to weight edges yet (the Sam and Tom edge and the Tom and Mary edge should perhaps be weighted at 2 because 'connected twice' -- connected by two events).

-Solomon


From: Gabor Csardi [mailto:csardi_at_rmki.kfki.hu] Sent: Wed 5/14/2008 4:01 AM
To: Messing, Solomon O.
Cc: R Help list
Subject: Re: [R] For Social Network Analysis-Graph Analysis - How to convert 2 mode data to 1 mode data?

Please stay on the list.

On Tue, May 13, 2008 at 06:05:15PM -0400, Messing, Solomon O. wrote:
> Gabor,

>
> By the way, this seems to work:

I'm a bit lost. So now you're converting your data frame to a matrix? Why? Or you're doing the two-mode to one-mode conversion here? It does not seem so to me.

Btw. there is a get.adjacency function in igraph to convert a graph to an adjacency matrix.

G.

>

> df.to.nxn <- function( x, y ){
> # x values will be the N x N values
> M <- matrix( nrow = length( unique( x ) ), ncol = length( unique( x
> ) ),
> dimnames = list( unique( x ), unique( x ) ) )
> M[ 1:length( unique( x ) ), 1:length( unique( x ) ) ] <- 0
> # initialize the values to 0
> for( i in 1:length( x ) ) {
> # iterate through rows of data
> index = which( y == y[i] )
> M[ as.character( x[ index ] ), as.character( x[ index ]
> ) ] = 1
> }
> M
> # return M, an N x N matrix
> }
--
Csardi Gabor <csardi_at_rmki.kfki.hu>    UNIL DGM



	[[alternative HTML version deleted]]

______________________________________________
R-help_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Received on Sat 17 May 2008 - 14:13:12 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Tue 20 May 2008 - 08:30:41 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-help. Please read the posting guide before posting to the list.

list of date sections of archive