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 <[email protected]> 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 > [email protected] > mob. +39.320.83.68.670 > skype umberto7755 > > > _______________________________________________ > igraph-help mailing list > [email protected] > https://lists.nongnu.org/mailman/listinfo/igraph-help _______________________________________________ igraph-help mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/igraph-help
