delete/modify an edge in graphviz - python

is there any way to delete an existing edge in a graph?
For example, when I draw an edge using
self.g.edge('a', 'b')
where self.g is my digraph, then I do
self.g.edge('a', 'b', _attributes={'arrowhead': 'dot'})
it draws another edge from a->b so now there are 2 edges instead of 1
basically what I'm trying to do is modify the existing edge
it works for nodes, but not edges

I don't think you can delete or modify anything with this library, but you can avoid multiple edges by initializing the graph with Digraph(strict=True) or similar.
The reason it seems to work for nodes is that Graphviz itself replaces an existing node if a new one with the same name is added later.

Related

networkx: giving a wrong direction for an edge

I am trying to read some dataframe to a networkx graph like this:
bipartGraph = nx.Graph()
bipartGraph.add_edge(618254814, 14337833)
bipartGraph.add_edge(618254882, 12087274)
When I display the edges using the bipartGraph.edges() function, I get the below:
[(14337833, 618254814), (618254882, 12087274)]
So, the direction of the first edge is reversed. I am trying to build a bipartite graph from a dataframe which I need to reuse to build an another graph. Is there any specific property of networkx I am missing?
At least in networkx 1.11 if your graph is undirected, an edge that is added as (u,v) may be returned as either (v,u) or (u,v). [I think this may have been changed in version 2.0]. This is because the underlying data structure is a dict, and there is no guarantee that a dict returns values in any particular order: Why items order in a dictionary changed in Python?.
If you really want a direction on your edge, you should make your graph a DiGraph.

removing edge from undirected edge graph-tool doesn't work when I swap vertices

I'm new to graph-tool python library and I'm just trying the basics.
I have a problem with remove_edge command.
let's get to the code:
import graph_tool.all as gt
g=gt.Graph(directed=False)
v1=g.add_vertex()
v2=g.add_vertex()
g.add_edge(v1,v2)
g.remove_edge(g.edge(v1,v2))
now it works fine but if I change the last line to:
g.remove_edge(g.edge(v2,v1))
the edge doesn't get removed.
shouldn't they be recognized as the same edge since my graph is undirected?
if not, how can I find a better way to make sure I have deleted the edge between two vertices in a non-multigraph undirected graph?
This is indeed a bug! It has been fixed now in version 2.24.

Testing if a graph is Directed or Undirected Graph from Edgelist file

I have a text document that is an edge list file. I know how to read the file (using Canopy Enthought), but I don't know how to get the information about the graph that I want.
Main question: Is there a way to detect whether this graph (created from the edge list file) is directed or undirected using networkx commands? Or just if it is weighted or unweighed?
I believe that you have to specify the type of the graph before using the edge list file. Because the edge list file is simply composed of tuples containing nodes to be connected without saying how they are connected. Thus, for instance if you create a graph G = nx.Graph(), then if the node pairs in the file are repeated, there will still be one edge between them and the order of the nodes does not matter; ((node1,node2) is equivalent to (node2,node1)). While if you created the graph as G = nx.DiGraph() the order of nodes makes a difference. Also, specifying G = nx.MultiGraph() more than one edge will exist in case of repetition. G = nx.MultiDiGraph() will have a different result when reading the edge list file. So, check the the graph types documentation to know which type you need to have.
To check if the graph is directed you can use
nx.is_directed(G), you can find the documentation here.
To check if the graph is weighted
There is no specific type to say if the graph has weighted edges or not. But a work around can be to check if edges contain an attribute called weight, as mentioned here. It can be done by
'weight' in G[1][2] # Returns true if an attribute called weight exists in the edge connecting nodes 1 and 2.

Is there a way to control line angle when producing graphs with pyDot

I wrote a python class to display and animate binary search trees. Yet the graphs produced by the pyDot edge and node commands don't seem to allow me to control the angle or direction of the arrows connecting each element of my tree.
There are lots of controls for shape of the nodes but there does not seem to be any control for angle of the lines. I was hoping to find some kind of minimum angle parameter to add to my edges as they are added to the graph?
This is a sample of my code where I draw nodes using the edge command:
def draw(parent_name, child_name):
# color for lines = red
edge = pydot.Edge(parent_name, child_name, color="#ff0000")
graph.add_edge(edge)
The end result is that my graphs for binary search trees don't look like the traditional tree structures when several nodes have only one child.
Here is a link to my project where you can see the otherwise working results:
http://www.embeddedcomponents.com/blogs/2013/12/visualizing-software-tree-structures/
from pydot documentation:
create will write the graph to a temporary dot file and process
it with the program given by 'prog' (which defaults to 'twopi'),
reading the Postscript output and returning it as a string is the
operation is successful.
it is not possible to directly control edges angels using the dot language, but adding invisible edges can give you the result you want, see an example here that generates the following graph:

Group vertices in clusters using NetworkX

I am trying to represent graphically some graphs, and I need to group in clusters some nodes that have a common characteristics.
I am using NetworkX, and I need to do something similar with the graph from this tutorial, from the slide 44, left figure.
I want to draw some delimiting line around each cluster. My current code is like that:
vec = self.colors
colors = (linspace(0, 1, len(set(vec))) * 20 + 10)
nx.draw_circular(g, node_color=array([colors[x] for x in vec]))
show()
I wish to find an example and see how can I use networkx to cluster the graph.
I'm not positive what your question is. I think you're asking "how do I get networkx to put some nodes close together"
Before I launch into the answer, the drawing documentation for networkx is here: http://networkx.lanl.gov/reference/drawing.html
So that figure you're asking about has 4 different communities that are clustered based on having lots of edges within each community and not many outside.
If you don't want to put much effort into it, spring_layout is often good for putting tightly knit communities together. The basic algorithm of spring_layout acts as if the edges are springs (and nodes repel). So lots of edges keeps nodes close together. Note that it initializes the positions randomly, so each time you'll get a different output.
The easiest way to do this is just
nx.draw_spring(G)
But maybe you want more. If you want to, you can fix every single node's position. Define a dict, usually named pos.
pos = {}
for node in G.nodes_iter():
pos[node] = (xcoord, ycoord).
where xcoord and ycoord are the coordinates you want the node to be at.
Then just do
draw_networkx(G, pos = pos)
That's often a lot of effort. So sometimes you just tell it a few of them have to be in particular places, and let networkx do the rest
Define fixedpos for a few nodes and then run
spring_layout
telling it what nodes are fixed and giving it fixedpos as the initial positions. Then it will hold those fixed and fit everything else around.
Here is some code which generates a network that has 4 completely connected parts and a few other edges between them. (actually it generates a complete network and then deletes all but a few edges between these parts). Then it draws it with a simple spring layout. Then it fixes 4 of them to be at the corners of a square and places the other nodes around those fixed positions.
import networkx as nx
import random
import pylab as py
from math import floor
G = nx.complete_graph(20)
for edge in G.edges():
if floor(edge[0]/5.)!=floor(edge[1]/5.):
if random.random()<0.95:
G.remove_edge(edge[0],edge[1])
nx.draw_spring(G)
py.show()
fixedpos = {1:(0,0), 6:(1,1), 11:(1,0), 16:(0,1)}
pos = nx.spring_layout(G, fixed = fixedpos.keys(), pos = fixedpos)
nx.draw_networkx(G, pos=pos)
py.show()
You can also specify weights to the edges, pass the weights to spring_layout and larger weights will tell it to keep the corresponding nodes closer together. So once you've identified your communities, increase weights within the communities/clusters if necessary to keep them close together.
Note that you can also specify what color to make each node, so it is straightforward to specify the color for each community/cluster.
If you then want to draw curves around each of those clusters, you'll have to do that through matplotlib.

Categories

Resources