For Social Network Analysis-Graph Analysis - How to convert 2 mode data to 1 mode data?

View: New views
8 Messages — Rating Filter:   Alert me  

For Social Network Analysis-Graph Analysis - How to convert 2 mode data to 1 mode data?

by messings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

 

Does anyone know of a package in R that has a function to convert
network data (e.g. an adjacency matrix or ) from 2-mode to 1-mode?  I am
conducting social network analysis.  I know that Pajek has this function
under Net --> Transform --> 2-mode to 1-mode --> Rows.  I have searched
the documentation under packages 'sna', 'network', 'igraph', and
'dynamicgraph' but I was not able to identify a comparable function.  

 

I would just export my data to Pajek and import it to R, but I'm going
to have to generate hundreds of these graphs, so it would take quite a
bit of time to do it this way.  

 

Thanks,

 

Solomon

 


        [[alternative HTML version deleted]]

______________________________________________
R-help@... 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.

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

by Gabor Csardi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Solomon, if i understand two-mode networks properly (they're bipartite, right?),
then this is not hard to do with igraph. Basically, for each vertex create an
order=2 neighborhood, and then create a graph from the adjacency list,
it is something like this:

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
}

It does not check that the graph is indeed two-mode, and it keeps the
vertices given in the 'keep' argument. 'keep' is made of igraph vertex ids.
You can use it like this:

g <- graph.ring(10)
keep <- seq(0,8,by=2) ## we keep the 'even' vertices

g2 <- two.to.one(g, keep)
write.graph(two.to.one(g, keep), format="pajek", file="/tmp/a.net")

I haven't tested it much. We'll have a better function in the next igraph version.
Gabor

On Fri, May 09, 2008 at 03:37:05PM -0400, Messing, Solomon O. wrote:

> Hi,
>
>  
>
> Does anyone know of a package in R that has a function to convert
> network data (e.g. an adjacency matrix or ) from 2-mode to 1-mode?  I am
> conducting social network analysis.  I know that Pajek has this function
> under Net --> Transform --> 2-mode to 1-mode --> Rows.  I have searched
> the documentation under packages 'sna', 'network', 'igraph', and
> 'dynamicgraph' but I was not able to identify a comparable function.  
>
>  
>
> I would just export my data to Pajek and import it to R, but I'm going
> to have to generate hundreds of these graphs, so it would take quite a
> bit of time to do it this way.  
>
>  
>
> Thanks,
>
>  
>
> Solomon
>
>  
>
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help@... 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.

--
Csardi Gabor <csardi@...>    UNIL DGM

______________________________________________
R-help@... 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.

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

by messings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Gabor,

Thank you for your help, and thanks for making the excellent igraph
package.  The function below seems not generate an edge list that works
for my data.  I coerced a my data from a data frame using
graph.data.frame.  

You asked in your previous post if 2-mode networks are bipartite.  I
believe the answer is yes.  However, in

Hanneman, Robert A. and Mark Riddle.  2005.  Introduction to social
network methods.  Riverside, CA:  University of California, Riverside (
published in digital form at http://faculty.ucr.edu/~hanneman/ )

I found the following:

"Two-mode data are sometimes stored in a second way, called the
"bipartite" matrix.  A bipartite matrix is formed by adding the rows as
additional columns, and columns as additional rows."

Did I need to convert my data frame to a bipartite matrix before
applying the two.to.one function?

Solomon


>-----Original Message-----
>From: Gabor Csardi [mailto:csardi@...]
>Sent: Saturday, May 10, 2008 1:09 PM
>To: Messing, Solomon O.
>Cc: r-help@...
>Subject: Re: [R] For Social Network Analysis-Graph Analysis - How to
convert 2
>mode data to 1 mode data?
>
>Solomon, if i understand two-mode networks properly (they're bipartite,
>right?),
>then this is not hard to do with igraph. Basically, for each vertex
create an
>order=2 neighborhood, and then create a graph from the adjacency list,
>it is something like this:
>
>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
>}
>
>It does not check that the graph is indeed two-mode, and it keeps the
>vertices given in the 'keep' argument. 'keep' is made of igraph vertex
ids.
>You can use it like this:
>
>g <- graph.ring(10)
>keep <- seq(0,8,by=2) ## we keep the 'even' vertices
>
>g2 <- two.to.one(g, keep)
>write.graph(two.to.one(g, keep), format="pajek", file="/tmp/a.net")
>
>I haven't tested it much. We'll have a better function in the next
igraph

>version.
>Gabor
>
>On Fri, May 09, 2008 at 03:37:05PM -0400, Messing, Solomon O. wrote:
>> Hi,
>>
>>
>>
>> Does anyone know of a package in R that has a function to convert
>> network data (e.g. an adjacency matrix or ) from 2-mode to 1-mode?  I
am
>> conducting social network analysis.  I know that Pajek has this
function
>> under Net --> Transform --> 2-mode to 1-mode --> Rows.  I have
searched
>> the documentation under packages 'sna', 'network', 'igraph', and
>> 'dynamicgraph' but I was not able to identify a comparable function.
>>
>>
>>
>> I would just export my data to Pajek and import it to R, but I'm
going
>> to have to generate hundreds of these graphs, so it would take quite
a

>> bit of time to do it this way.
>>
>>
>>
>> Thanks,
>>
>>
>>
>> Solomon
>>
>>
>>
>>
>> [[alternative HTML version deleted]]
>>
>> ______________________________________________
>> R-help@... 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.
>
>--
>Csardi Gabor <csardi@...>    UNIL DGM

______________________________________________
R-help@... 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.

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

by Gabor Csardi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Solomon,

On Tue, May 13, 2008 at 05:53:44PM -0400, Messing, Solomon O. wrote:

> Hi Gabor,
>
> Thank you for your help, and thanks for making the excellent igraph
> package.  The function below seems not generate an edge list that works
> for my data.  I coerced a my data from a data frame using
> graph.data.frame.  
>
> You asked in your previous post if 2-mode networks are bipartite.  I
> believe the answer is yes.  However, in
>
> Hanneman, Robert A. and Mark Riddle.  2005.  Introduction to social
> network methods.  Riverside, CA:  University of California, Riverside (
> published in digital form at http://faculty.ucr.edu/~hanneman/ )
>
> I found the following:
>
> "Two-mode data are sometimes stored in a second way, called the
> "bipartite" matrix.  A bipartite matrix is formed by adding the rows as
> additional columns, and columns as additional rows."
>
> Did I need to convert my data frame to a bipartite matrix before
> applying the two.to.one function?

No. The function i've sent assumes that your network is bipartite, i.e.
if A and B are connected by an edge, then they're assumed to be
different types of nodes. Just create the graph, calculate the 'keep'
parameter, I assume that you know this from external information, and
then call the function.

G.

> Solomon
>
>
> >-----Original Message-----
> >From: Gabor Csardi [mailto:csardi@...]
> >Sent: Saturday, May 10, 2008 1:09 PM
> >To: Messing, Solomon O.
> >Cc: r-help@...
> >Subject: Re: [R] For Social Network Analysis-Graph Analysis - How to
> convert 2
> >mode data to 1 mode data?
> >
> >Solomon, if i understand two-mode networks properly (they're bipartite,
> >right?),
> >then this is not hard to do with igraph. Basically, for each vertex
> create an
> >order=2 neighborhood, and then create a graph from the adjacency list,
> >it is something like this:
> >
> >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
> >}
> >
> >It does not check that the graph is indeed two-mode, and it keeps the
> >vertices given in the 'keep' argument. 'keep' is made of igraph vertex
> ids.
> >You can use it like this:
> >
> >g <- graph.ring(10)
> >keep <- seq(0,8,by=2) ## we keep the 'even' vertices
> >
> >g2 <- two.to.one(g, keep)
> >write.graph(two.to.one(g, keep), format="pajek", file="/tmp/a.net")
> >
> >I haven't tested it much. We'll have a better function in the next
> igraph
> >version.
> >Gabor
> >
> >On Fri, May 09, 2008 at 03:37:05PM -0400, Messing, Solomon O. wrote:
> >> Hi,
> >>
> >>
> >>
> >> Does anyone know of a package in R that has a function to convert
> >> network data (e.g. an adjacency matrix or ) from 2-mode to 1-mode?  I
> am
> >> conducting social network analysis.  I know that Pajek has this
> function
> >> under Net --> Transform --> 2-mode to 1-mode --> Rows.  I have
> searched
> >> the documentation under packages 'sna', 'network', 'igraph', and
> >> 'dynamicgraph' but I was not able to identify a comparable function.
> >>
> >>
> >>
> >> I would just export my data to Pajek and import it to R, but I'm
> going
> >> to have to generate hundreds of these graphs, so it would take quite
> a
> >> bit of time to do it this way.
> >>
> >>
> >>
> >> Thanks,
> >>
> >>
> >>
> >> Solomon
> >>
> >>
> >>
> >>
> >> [[alternative HTML version deleted]]
> >>
> >> ______________________________________________
> >> R-help@... 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.
> >
> >--
> >Csardi Gabor <csardi@...>    UNIL DGM

--
Csardi Gabor <csardi@...>    UNIL DGM

______________________________________________
R-help@... 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.

Parent Message unknown Re: For Social Network Analysis-Graph Analysis - How to convert 2 mode data to 1 mode data?

by Gabor Csardi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...>    UNIL DGM

______________________________________________
R-help@... 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.

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

by messings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...]
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@...>    UNIL DGM



        [[alternative HTML version deleted]]

______________________________________________
R-help@... 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.

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

by Gabor Csardi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Solomon, sorry for the delay. In igraph vertices are numbered from 0, so you need

keep <- 0:3

and then the function i've sent seems to work. But i can see that you also have a solution
now.

Gabor

On Sat, May 17, 2008 at 09:32:27AM -0400, Messing, Solomon O. wrote:

> 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@...]
> 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@...>    UNIL DGM
>

--
Csardi Gabor <csardi@...>    UNIL DGM

______________________________________________
R-help@... 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.

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

by messings :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Gabor,
 
Thanks for clearing that up.  There still seems to be a problem, though.  After executing:
 
###############################################################################
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)
V(g2)$name = V(g)$name[1:4]
g2
##############################################################33

I get the following output:

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

This appears to be because the new igraph object is labeled correctly, but is not in order:

> g2 = two.to.one(g, keep)
> g2
Vertices: 4
Edges: 4
Directed: FALSE
Edges:
         
[0] 1 -- 0
[1] 0 -- 2
[2] 0 -- 3
[3] 2 -- 3

> V(g2)$name
[1] "1" "0" "2" "3"

So when I try to label the new object, the labels are assigned to the verticies incorrectly.  What is the best solution?  Could I create a new graph by ordering g2 by id?  

Thanks,

Solomon




________________________________

From: Gabor Csardi [mailto:csardi@...]
Sent: Tue 5/20/2008 3:08 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?



Solomon, sorry for the delay. In igraph vertices are numbered from 0, so you need

keep <- 0:3

and then the function i've sent seems to work. But i can see that you also have a solution
now.

Gabor

On Sat, May 17, 2008 at 09:32:27AM -0400, Messing, Solomon O. wrote:

> 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@...]
> 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@...>    UNIL DGM
>

--
Csardi Gabor <csardi@...>    UNIL DGM



        [[alternative HTML version deleted]]

______________________________________________
R-help@... 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.