igraph-help
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [igraph] help with graph.union.by.name


From: Umberto Medicamento
Subject: Re: [igraph] help with graph.union.by.name
Date: Wed, 05 Nov 2014 17:25:37 +0100
User-agent: Internet Messaging Program (IMP) H5 (6.2.2)

Thanks a lot Gabor,

Hi,

the latest version of igraph handles vertex names in graph operators,
so you don't actually need these extra functions.

Great, does it handles edge weights too and other vertex/edge attributes?

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.

It runs with my data, can I try your tests?

Umberto

Gabor

Gábor Csárdi <address@hidden> ha scritto:

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

_______________________________________________
igraph-help mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/igraph-help

--
Dr. Agr. Umberto Medicamento
PhD, MoS
address@hidden
mob. +39.320.83.68.670
skype umberto7755




reply via email to

[Prev in Thread] Current Thread [Next in Thread]