I am trying to generate the Waxman random graph using the built-in function which works fine and generates the Waxman graph.
Later in my code, I am writing the above-generated graph using graphml as:
nx.write_graphml(my_graph_waxman, "waxman_Iteration.graphml")
This writing function gives the error:
networkx.exception.NetworkXError: GraphML writer does not support <class 'tuple'> as data values.
My complete code is here:
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
my_graph_waxman=nx.waxman_graph(6, beta=0.8, alpha=0.6, L=None, domain=(0, 0, 1, 1), metric=None, seed=None)
nx.draw(my_graph_waxman, with_labels=True, font_weight='normal')
plt.axis('on')
plt.show()
nx.write_graphml(my_graph_waxman, "waxman_Iteration.graphml")
Related
I would like to generate reproducible plots. With networkx is possible to pass the random state to the layout. That is to ensure the plot is the same. When doing the same with holoviews I am getting an error.
%pylab inline
import pandas as pd
import networkx as nx
import holoviews as hv
# generating the graph
G = nx.Graph()
ndxs = [1, 2, 3, 4]
G.add_nodes_from(ndxs)
G.add_weighted_edges_from([(1,2,0), (1,3,1), (1,4,-1),
(2,4,1), (2,3,-1), (3,4,10)])
# drawing with networkx
nx.draw(G, nx.spring_layout(G, random_state=100))
# drawing with holoviews/bokeh
hv.extension('bokeh')
%opts Graph [width=400 height=400]
layout = nx.layout.spring_layout(G, random_state=100)
hv.Graph.from_networkx(G, layout)
>>> TypeError: 'dict' object is not callable
The first issue is that the Graph.from_networkx method accepts the layout function not the dictionary that is output by that function. If you want to pass arguments to the function you can do so as keyword argument, e.g.:
hv.Graph.from_networkx(G, nx.layout.spring_layout, random_state=42)
In my version of networkx random_state is not an accepted argument to the layout functions in which case you can set the seed directly with NumPy:
np.random.seed(42)
hv.Graph.from_networkx(G, nx.layout.spring_layout)
I try to save a graph in graph6 format in Python with networkx. The obvious way does not seem to work:
import networkx as nx
g = nx.Graph()
g.add_edge('1','2')
nx.write_graph6(g,"anedge.g6")
g1 = nx.read_graph6("anedge.g6")
import matplotlib.pyplot as plt
nx.draw(g1)
plt.savefig("anedge.pdf")
This makes a pdf file showing a graph with two isolated vertices instead of two connected vertices.
Using g.add_edge(0, 1) instead of g.add_edge('1','2') it should work:
import networkx as nx
import matplotlib.pyplot as plt
g = nx.Graph()
g.add_edge(0, 1)
nx.write_graph6(g, 'anedge.g6')
g1 = nx.read_graph6('anedge.g6')
nx.draw(g1)
plt.savefig("anedge.pdf")
This is actually exposing a bug in the networkx graph6 generator when the nodes are not consecutively ordered from zero. Bug fix is here https://github.com/networkx/networkx/pull/2739
My code as follows:
import ConfigParser
import sys
import time
import matplotlib.pyplot as plt
import networkx as nx
import json
from networkx.algorithms import bipartite
def create_graph(senators):
G= nx.Graph()
G.add_nodes_from(senators)
return G
senators=["ab","cd","ef"]
graph = create_graph(senators)
nx.draw(graph,with_labels=True)
plt.savefig("p1.png")
graph.clear()
graph = nx.DiGraph()
print graph.nodes()
nx.draw(graph,with_labels=True)
plt.savefig("p2.png")
In my code I try to draw two pictures:p1.png and p2.png. After I draw p1.png , I clear graph. However, p2.png has the same node with p1.png.
I don't know what's wrong with my code . Because I have clear graph, so there should be nothing in p2.png
What is the problem?
There are two separate notions of "clearing". One is removing nodes and edges from the graph (graph.clear) and the other is erasing the figure (plt.clf()). You are removing the nodes and edges but not clearing the figure axes. So what you are saving in p2.png is just the original p1.png figure. Try adding a plt.clf() before the second nx.draw().
I'm using Python to simulate a process that takes place on directed graphs. I would like to produce an animation of this process.
The problem that I've run into is that most Python graph visualization libraries combine pairs of directed edges into a single edge. For example, NetworkX draws only two edges when displaying the following graph, whereas I would like to display each of the four edges separately:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.MultiDiGraph()
G.add_edges_from([
(1, 2),
(2, 3),
(3, 2),
(2, 1),
])
plt.figure(figsize=(8,8))
nx.draw(G)
I would like to display something like this, with each parallel edge drawn separately:
The question R reciprocal edges in igraph in R seems to deal with the same issue, but the solution there is for the R igraph library, not the Python one.
Is there an easy way to produce this style of plot using an existing Python graph visualization library? It would be a bonus if it could support multigraphs.
I'm open to solutions that invoke an external program to produce the images. I'd like to generate a whole series of animation frames, so the solution must be automated.
The Graphviz tools appear to display distinct edges.
For example, giving this:
digraph G {
A -> B;
A -> B;
A -> B;
B -> C;
B -> A;
C -> B;
}
to dot produces:
Graphviz's input language is pretty simple so you can generate it on your own, though searching for "python graphviz" does turn up a couple of libraries including a graphviz module on PyPI.
Here's python that generates the above graph using the graphviz module:
from graphviz import Digraph
dot = Digraph()
dot.node('A', 'A')
dot.node('B', 'B')
dot.node('C', 'C')
dot.edges(['AB', 'AB', 'AB', 'BC', 'BA', 'CB'])
print(dot.source)
dot.render(view=True)
Maybe I am a little late but I found another solution to you issue. I am posting it so that it can be helpful if somebody has the same problem.
It is possible to plot directed graphs with networkx using matplotlib in a way that the edges appear separately, by passing the argument connectionstyle to the function networkx.drawing.nx_pylab.draw:
import matplotlib.pyplot as plt
import networkx as nx
# create a directed multi-graph
G = nx.MultiDiGraph()
G.add_edges_from([
(1, 2),
(2, 3),
(3, 2),
(2, 1),
])
# plot the graph
plt.figure(figsize=(8,8))
nx.draw(G, connectionstyle='arc3, rad = 0.1')
plt.show() # pause before exiting
Here you see the result:
See also the documentation of matplotlib.patches.ConnectionStyle about the argument connectionstyle.
Using NetworkX, a possible workaround which avoids file I/O and uses dot via pydot for layout is:
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from io import BytesIO
g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g)
# `d` is a `pydot` graph object,
# `dot` options can be easily set
# attributes get converted from `networkx`,
# use set methods to control
# `dot` attributes after creation
png_str = d.create_png()
sio = BytesIO() # file-like string, appropriate for imread below
sio.write(png_str)
sio.seek(0)
img = mpimg.imread(sio)
imgplot = plt.imshow(img)
plt.show() # added to make the script wait before exiting
for why seek(0) is needed, see How to create an image from a string in python
If within the IPython (qt)console, then the above will print inline and a more direct approach is:
import networkx as nx
from IPython.display import Image
g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g)
png_str = d.create_png()
Image(data=png_str)
You can do it by using the matplotlib interface:
G=nx.MultiGraph ([(1, 2),
(2, 3),
(3, 2),
(2, 1)])
pos = {1: (0.4,0.5), 2: (0.5,0.5), 3: (0.6,0.5)}
nx.draw_networkx_nodes(G, pos, node_color = 'k', node_size = 100, alpha = 1)
ax = plt.gca()
for e in G.edges:
ax.annotate("",
xy=pos[e[0]], xycoords='data',
xytext=pos[e[1]], textcoords='data',
arrowprops=dict(arrowstyle="->", color="0.5",
shrinkA=5, shrinkB=5,
patchA=None, patchB=None,
connectionstyle="arc3,rad=rrr".replace('rrr',str(2*(e[2]-0.5))
),
),
)
plt.axis('off')
plt.show()
I want to build a directed graph and subscribe edges.
import os
import scipy as sc
import pylab
import networkx
import matplotlib.pyplot as plt
from networkx import *
from numpy import *
G=networkx.DiGraph()
R=[('S0','S1'),('S1','S2'),('S1','S7'),('S2','S3'),('S2','S6'),('S3','S4'),('S3','S6'),('S4','S5'),('S5','S6'),('S6','S7'),('S7','S8'),('S7','S5'),('S8','Sk') ]
G.add_edges_from([ (2,3,) ])
G.add_edges_from(R)
networkx.draw_circular(G)
plt.show()
plt.savefig("path.png");
Now I have done this. I built a graph, but I cannot think up how to subscribe edges. For example I want to mark S0 and S1 edge like "565", etc. It will make it more visual and demostrative.
Thanks in advance!
Instead of layouting and drawing in one single step (networkx.draw_circular(G)), you can layout and draw nodes, edges, node labels and edge labels separately. Here's a small example:
import networkx as nx
import matplotlib.pyplot as plt
G=nx.DiGraph()
R=[('S0','S1'),('S1','S2'),('S1','S7'),('S0','S7')]
G.add_edges_from(R)
# Calculate layout and get all positions
pos = nx.circular_layout(G)
# Draw everything
nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edge_labels(G, pos,
{
('S0', 'S1'): 'edge1',
('S1', 'S2'): 'edge2',
('S1', 'S7'): 'edge3',
('S0', 'S7'): 'edge4'
}
)
plt.axis('off')
plt.savefig("path.png");
plt.show()
For more information about what parameters can be passed to the different drawing functions, check the documentation.
You can draw nodes and egdes selectively with:
# nodes
networkx.draw_networkx_nodes(graph, pos, nodelist=[list of the nodes])
# edges
networkx.draw_networkx_edges(graph, pos, edgelist=[list of edges])
There are more options at http://networkx.lanl.gov/reference/drawing.html#module-networkx.drawing.nx_pylab
well, I wanted to do this:
and I did it. i.e. I wanted to mark edges. It seems simple, but it wasn't so. Really.
full image is here http://s019.radikal.ru/i603/1204/2a/921bc6badfae.png
import os
import scipy as sc
import pylab
import networkx
import matplotlib.pyplot as plt
from networkx import *
from numpy import *
G=networkx.DiGraph()
R=[('S0','S1'),('S1','S2'),('S1','S7'),('S2','S3'),('S2','S6'),('S3','S4'),('S3','S6'),('S4','S5'),('S5','S6'),('S6','S7'),('S7','S8'),('S7','S5'),('S8','Sk') ]
G.add_edges_from(R)
label={R[1]:'a',R[2]:'b',R[3]:'c'}
networkx.draw_networkx_edge_labels(G,pos=networkx.graphviz_layout(G),edge_labels=label)
networkx.draw_graphviz(G)
plt.show()
plt.savefig("path.png");