[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [igraph] help with graph.union.by.name
From: |
Gábor Csárdi |
Subject: |
Re: [igraph] help with graph.union.by.name |
Date: |
Wed, 5 Nov 2014 10:48:20 -0500 |
Hi,
the latest version of igraph handles vertex names in graph operators,
so you don't actually need these extra functions.
Actually, I can't even run your code, I get
> graph.difference.by.name(g1,g2)
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 2, 0
for all of the tests.
Gabor
On Wed, Nov 5, 2014 at 10:14 AM, Umberto Medicamento
<address@hidden> wrote:
> Hi all,
> I was applying the function graph.union.by.name over a list of weighted
> graphs.
> The function I used is as follows (it also provides for intersection and
> other operations).
> Unfortunately, I cannot recall where I found it.
>
> After uniting the first two graphs, I compared the result obtained both
> using the graph.union.by.name in its weighted and unweighted version.
>
> With the weighted form of the function I've got a (third) graph with 99
> nodes and 983 edges, while with its unweighted form I've got a (third) graph
> with 99 nodes and 638 edges.
>
> Anybody can help me to understand why?
>
> Thanks a lot, Umberto M.
>
>
> # READ: for weighted graphs change get.edges.as.data.frame = function(graph,
> keep.attributes=FALSE
> # to:
> # get.edges.as.data.frame = function(graph, keep.attributes=TRUE)
>
> safer.merge = function(
> x, y, by = intersect(names(x), names(y)),
> by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all,
> suffixes = c(".x",".y"), incomparables = NULL,
> indicate.origin=FALSE, allow.duplicates=FALSE,
> allow.duplicates.x=allow.duplicates, allow.duplicates.y=allow.duplicates,
> ...)
> {
> if ( !allow.duplicates.x & (sum(duplicated(x[,by.x]))!=0) )
> {
> stop("safer.merge: Duplicates found in x, but allow.duplicates.x is
> FALSE" )
> }
> if ( !allow.duplicates.y & (sum(duplicated(y[,by.y]))!=0) )
> {
> stop("safer.merge: Duplicates found in y, but allow.duplicates.y is
> FALSE" )
> }
> stopifnot( sum(is.na(x[,by.x])) == 0 )
> stopifnot( sum(is.na(y[,by.y])) == 0 )
>
> if ( indicate.origin )
> {
> stopifnot( !("was.in" %in% names(x) ) )
> stopifnot( !("was.in" %in% names(y) ) )
> x$was.in=rep(TRUE,nrow(x))
> y$was.in=rep(TRUE,nrow(y))
> }
>
> result = merge(x, y, by=by,
> by.x=by.x, by.y=by.y, all=all, all.x=all.x, all.y=all.y,
> sort=TRUE, suffixes=suffixes, incomparables=incomparables,
> ...)
>
> if ( indicate.origin & nrow(result) > 0 )
> {
> was.in.x = paste0("was.in", suffixes[1])
> was.in.y = paste0("was.in", suffixes[2])
> result[ is.na(result[,was.in.x]) , was.in.x] = FALSE
> result[ is.na(result[,was.in.y]) , was.in.y] = FALSE
> }
>
> return(result)
> }
>
> # Return graph vertices as a data.frame.
> # If keep.attributes == TRUE, the data.frame contains all vertex attributes.
> get.vertices.as.data.frame = function(graph, keep.attributes=TRUE)
> {
> stopifnot( length(V(graph)$name) == length(unique(V(graph)$name))) #
> Vertex names must be unique
> if ( is.null(V(graph)$name) ) return(data.frame(V=character()))
> d = data.frame(V=V(graph)$name)
> if ( keep.attributes )
> {
> # Bind attributes if requested
> attr.names = list.vertex.attributes(graph)
> d.a = as.data.frame(lapply( attr.names,
> function(attr,
> g){get.vertex.attribute(g,attr)},
> graph))
> names(d.a) = attr.names
> d = cbind(d,d.a)
> }
> return(d)
> }
>
> # Return graph edges as a mergable data.frame
> # If the graph is undirected, the result will have all V1 <= V2
> # If keep.attributes == TRUE, the data.frame contains all edge attributes.
> get.edges.as.data.frame = function(graph, keep.attributes=TRUE)
> {
> stopifnot( length(V(graph)$name) == length(unique(V(graph)$name))) #
> Vertex names must be unique
> m = get.edgelist(graph)
> if ( !is.directed(graph) )
> {
> ix.rev = m[,1] > m[,2] # Choose which pairs to switch
> m[ix.rev,1:2] = m[ix.rev,2:1] # Switch
> }
> d = as.data.frame(m)
> if ( keep.attributes )
> {
> # Bind attributes if requested
> attr.names = list.edge.attributes(graph)
> d.a = as.data.frame(lapply( attr.names,
> function(attr,
> g){get.edge.attribute(g,attr)},
> graph))
> names(d.a) = attr.names
> d = cbind(d,d.a)
> }
> return(d)
> }
>
> check.graphs.for.set.operations = function(g1, g2) {
> if(is.directed(g1) & !is.directed(g2) ||
> !is.directed(g1) & is.directed(g2))
> stop("g1 and g2 must be both directed or both undirected")
> if(vcount(g1) > 0 & is.null(V(g1)$name))
> stop("g1 must have a vertex name attribute")
> if(vcount(g2) > 0 & is.null(V(g2)$name))
> stop("g2 must have a vertex name attribute")
> }
>
> # Create an intersection of two graphs.
> # This function correctly intersects the graphs based
> # on the name attributes, such that:
> # Any vertex that is in g1 and g2 is in the result.
> # Any edge that is in g1 and g2 is in the result.
> # This function preserves some attributes, but not all.
> graph.intersection.by.name = function(g1, g2,
> keep.x.vertices = FALSE,
> keep.x.vertex.attributes = FALSE,
> keep.x.edge.attributes = FALSE)
> {
> check.graphs.for.set.operations(g1, g2)
>
> # Construct data.frames of nodes and edges
> dv1 = get.vertices.as.data.frame(g1,
> keep.attributes=keep.x.vertex.attributes)
> dv2 = get.vertices.as.data.frame(g2)
> de1 = get.edges.as.data.frame(g1, keep.attributes=keep.x.edge.attributes)
> de2 = get.edges.as.data.frame(g2)
>
> # Merge data.frames and construct result
> if ( keep.x.vertices )
> dv = dv1
> else
> dv = safer.merge(dv1, dv2)
> de = safer.merge(de1, de2)
> g = graph.data.frame(de, directed=is.directed(g1), vertices=dv)
> return(g)
> }
>
> # Create union of two graphs.
> # This function correctly unions the graphs based
> # on the name attributes, such that:
> # Any vertex that is in g1 or g2 is in the result.
> # Any edge that is in g1 or g2 is in the result.
> # However, this function does NOT preserve other attributes.
> graph.union.by.name = function(g1, g2)
> {
> check.graphs.for.set.operations(g1, g2)
>
> # Construct data.frames of nodes and edges
> dv1 = get.vertices.as.data.frame(g1)
> dv2 = get.vertices.as.data.frame(g2)
> de1 = get.edges.as.data.frame(g1)
> de2 = get.edges.as.data.frame(g2)
>
> # Merge data.frames and construct result
> dv = safer.merge(dv1, dv2, all=TRUE)
> de = safer.merge(de1, de2, all=TRUE)
> g = graph.data.frame(de, directed=is.directed(g1), vertices=dv)
> return(g)
> }
>
> # Create difference of two graphs.
> # This function correctly diffs the graphs based
> # on the name attributes. Note that this difference applies
> # only to the edges, not the vertices, so that:
> # Any vertex that is in g1 is in the result.
> # Any edge that is in g1 but not in g2 is in the result.
> # However, this function does NOT preserve other attributes.
> graph.difference.by.name = function(g1, g2,
> keep.x.vertex.attributes = FALSE,
> keep.x.edge.attributes = FALSE)
> {
> check.graphs.for.set.operations(g1, g2)
>
> # Construct data.frames of nodes and edges
> dv = get.vertices.as.data.frame(g1,
> keep.attributes=keep.x.vertex.attributes)
> de1 = get.edges.as.data.frame(g1, keep.attributes=keep.x.edge.attributes)
> de2 = get.edges.as.data.frame(g2)
>
> # Merge data.frames and construct result
> de = safer.merge(de1, de2, all=TRUE, indicate.origin=TRUE) # All edges
> if( nrow(de) > 0 ) {
> de = de[ (de$was.in.x & !de$was.in.y) , # Remove g2
> edges
> setdiff(names(de),c("was.in.x","was.in.y")) ] # Keep
> attributes from g1
> g = graph.data.frame(de, directed=is.directed(g1), vertices=dv) #
> The new graph
> } else {
> g = delete.edges(g1, E(g1))
> }
> return(g)
> }
>
>
> # Test/demonstration code
> if (FALSE)
> {
>
> # Load library and set parameters for better printing
> library(igraph)
> igraph.options(print.vertex.attributes=TRUE)
> igraph.options(print.edge.attributes=TRUE)
>
> # Define input graphs
> g1 <- graph.formula(a-b-c)
> V(g1)$v.attr=c(1,2,3)
> E(g1)$e.attr=c(5,7)
> g2 <- graph.formula(b-c-d)
>
> # Test the functions
> graph.intersection.by.name(g1,g2) # Vertices are intersected as well
> graph.union.by.name(g1,g2) # Vertices are unioned as well
> graph.difference.by.name(g1,g2) # Vertices from x (g1) are used
>
> # graph.intersection.by.name() has some extra parameters
> graph.intersection.by.name(g1,g2,
> keep.x.vertices = TRUE) # Keep all x
> vertices (only intersect edges)
>
> graph.intersection.by.name(g1,g2,
> keep.x.vertices = FALSE, # Keep all x
> vertices (only intersect edges)
> keep.x.vertex.attributes = TRUE, # Don't throw
> away V(g1) attributes
> keep.x.edge.attributes = TRUE) # Don't throw
> away E(g1) attributes
>
> # graph.difference.by.name() has some extra parameters
> graph.difference.by.name(g1,g2,
> keep.x.vertex.attributes = TRUE, # Don't throw
> away V(g1) attributes
> keep.x.edge.attributes = TRUE) # Don't throw
> away E(g1) attributes
>
> }
>
>
> --
> Dr. Agr. Umberto Medicamento
> PhD, MoS
> address@hidden
> mob. +39.320.83.68.670
> skype umberto7755
>
>
> _______________________________________________
> igraph-help mailing list
> address@hidden
> https://lists.nongnu.org/mailman/listinfo/igraph-help