How to show node labels when using matplotlib.pyplot? - python

I'm using Python to conduct social network analysis, very simple kind, and as a newbie (to both SNA and Python).
When drawing a graph using Terminal on my mac, I've tried every method I can but still can only draw nodes and edges, but no label of nodes in or beside them.
What scripts should I use to make the labels visible?
>>> import networkx as nx
>>> import networkx.generators.small as gs
>>> import matplotlib.pyplot as plt
>>> g = gs.krackhardt_kite_graph()
>>> nx.draw(g)
>>> plt.show()

EdChum gave a good answer. Another option which will by default not show the axes and produces a graph that takes up slightly more of the figure is to use nx.draw but give it the argument with_labels = True. (for nx.draw, you need to set with_labels to True, but for nx.draw_networkx it defaults to True).
import networkx as nx
import networkx.generators.small as gs
import matplotlib.pyplot as plt
g = gs.krackhardt_kite_graph()
nx.draw(g,with_labels=True)
plt.savefig('tmp.png')
Be aware that there is a bug such that sometimes plt.show() will not show the labels. From what I've been able to tell, it's not in networkx, but rather has something to do with the rendering. It saves fine, so I haven't worried about following up on it in detail. It shows up for me using ipython on a macbook. Not sure what other systems it's on. More detail at pylab/networkx; no node labels displayed after update

Try using draw_networkx:
import networkx as nx
import networkx.generators.small as gs
import matplotlib.pyplot as plt
g = gs.krackhardt_kite_graph()
nx.draw_networkx(g)
plt.show()
This results in:
with_labels is by default True so not necessary to specify

Related

How to prevent an osmnx figure from being shown in Python (jupyter)

Using matplotlib we can prevent a figure from being shown using the close function
import matplotlib.pyplot as plt
a = range(0,5)
b = range(0,10,2)
plt.plot(a,b, 'r-*')
plt.close()
Because osmnx uses matplotlib in background, I though the close function could have been used in the same way
import matplotlib.pyplot as plt
import osmnx as ox
graph = ox.graph_from_bbox(41.97278, 41.97614, -87.73993, -87.73755, network_type='drive')
ox.plot_graph(graph,
bbox=[41.97278, 41.97614, -87.73993, -87.73755],
)
plt.close()
Unfortunately the figure is still displayed.
Is there a way to prevent the figure from being shown ?
Thanks in advance.
Did you read the OSMnx documentation for that function?
show (bool) – if True, call pyplot.show() to show the figure
close (bool) – if True, call pyplot.close() to close the figure
The use of these parameters are also demonstrated in the OSMnx usage examples.
import osmnx as ox
bbox = 41.97278, 41.97614, -87.73993, -87.73755
G = ox.graph_from_bbox(*bbox, network_type='drive')
fig, ax = ox.plot_graph(G, bbox=bbox, show=False, close=True)

Separate edge arrows in python/networkx directed graph

I would like to obtain something similar to this:
using the python library networkx. I can generate a similar directed graph using the following code:
import matplotlib.pyplot as plt
import networkx as nx
G = nx.DiGraph()
G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')
nx.draw(G, node_color='w', edgecolors='k', width=2.0, with_labels=True)
plt.show()
which produces:
However, the arrows between the nodes 3 and 4 are superimposed, and it just looks as a single arrow with two heads. Would it be possible to separate them slightly, in order to make more evident the fact that there are two edges over there and not just one? (I know that it can be done using pygraphviz, but I am trying to do it using matplotlib).
I forked the networkx drawing utilities some time ago to work around this and several other issues I have had. The package is called netgraph, and supports drawing of networkx and igraph graph structures (as well as simple edge lists).
It uses matplotlib under the hood, and exposes the created artists so that it easy to manipulate them further even if there is not in-built functionality to do so.
#!/usr/bin/env python
"""
https://stackoverflow.com/questions/61412323/separate-edge-arrows-in-python-networkx-directed-graph
"""
import matplotlib.pyplot as plt
import networkx as nx
import netgraph
G = nx.DiGraph()
G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')
netgraph.draw(G, node_color='w', edge_color='k', edge_width=2.0, node_labels={str(ii) : str(ii) for ii in range(1,5)})
plt.show()
You'll need a MultiDiGraph for multiple edges between two nodes:
G = nx.MultiDiGraph()
G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')
To visualise the network you could use Graphviz which does display parallel edges. You could write the graph in dot and display the graph with graphviz.Source:
from networkx.drawing import nx_pydot
from graphviz import Source
nx_pydot.write_dot(G, 'multig.dot')
Source.from_file('multig.dot')

How to adjust size of Seaborn distribution graph

I would like to adjust the size of this distribution plot in Seaborn. I tried a few ways from online tutorials and the docs but nothing seemed to actually work. I find this really confusing as it appears different plots such as plt, sns have different functions which don't seem to work interchangeably...
My code:
import seaborn as sns
g = sns.distplot(df['data'])
g.fig.set_figwidth(20)
g.fig.set_figheight(10)
g is an matplotlib.axes._subplots.AxesSubplot (try type(g) to see that). If you do a dir(g) you would see that it has no fig method/attribute. But it has a figure attribute. So change your code to reflect that and you would have what you need.
import seaborn as sns
g = sns.distplot(df['data'])
g.figure.set_figwidth(20)
g.figure.set_figheight(10)
Thanks #Sinan Kurmus's answer, just an alternative solution:
plt.figure(figsize=(30,10)) # Use this line
# plt.gcf().subplots_adjust(left = 0.3)
g = sns.distplot(df['data'])

Draw graph in NetworkX

I'm trying to draw any graph in NetworkX, but get nothing, not even errors:
import networkx as nx
import matplotlib.pyplot as plt
g1=nx.petersen_graph()
nx.draw(g1)
Add to the end:
plt.show()
import networkx as nx
import matplotlib.pyplot as plt
g1 = nx.petersen_graph()
nx.draw(g1)
plt.show()
When run from an interactive shell where plt.ion() has been called, the plt.show() is not needed. This is probably why it is omitted in a lot of examples.
If you run these commands from a script (where plt.ion() has not been called), the plt.show() is needed. plt.ion() is okay for interactive sessions, but is not recommended for scripts.
in ipython notebook, just type in magic
%matplotlib inline
or
%matplotlib notebook
You can easily plot with networkx graphs using jupyter notebook. See first example.
OR, you can use Bokeh to plot graphs, which adds useful features.
The package holoviews makes it even simpler to plot a graphs with bokeh. It adds features like automatic highlighting and show of labels while hovering over nodes. However, editing colors etc. seems to be an issue.
%pylab inline
# `pylab notebook` # for interactive plots
import pandas as pd
import networkx as nx
import holoviews as hv
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) ] )
nx.draw(G, nx.spring_layout(G, random_state=100))
And here the example with bokeh and holoview:
hv.extension('bokeh')
%opts Graph [width=400 height=400]
padding = dict(x=(-1.1, 1.1), y=(-1.1, 1.1))
hv.Graph.from_networkx(G, nx.layout.spring_layout).redim.range(**padding)
You should give it a try and plot it in your notebook to see the difference.
It works fine by adding:
import matplotlib.pyplot as plt
plt.show()
to your code. mine worked fine.

open .dot formatted graph from python

As I can plot curves with matplotlib in python, I wonder if there are any ways to show .dot graphs somehow. I have a string describing a graph:
graph name{
1--2;
}
Somehow pass it to a viewer program?
Maybe not exactly what you intend to do, but you can use pygraphviz and print your graph to a file:
import pygraphviz as pgv
G=pgv.AGraph()
G.add_edge('1','2')
G.layout()
G.draw('file.png')
(or you can just import a .dot file using G = pgv.AGraph('file.dot'))
Then you can always use Image or openCV to load your file and show it in the viewer.
I don't think pygraphviz allows you to to that directly though.
EDIT:
I recently found out another way and remembered your question: NetworkX lets you do that. Here's how:
Either create your graph using NetworkX directly. It is convenient that most of the commands of NetworkX are the same as those in pygraphviz. Then simply send to matplotlib and plot it there:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edge('1','2')
nx.draw(G)
plt.show()
Or you can import your .dot file through pygraphviz and then transform it into a networkx object:
import pygraphviz as pgv
import networkx as nx
import matplotlib.pyplot as plt
Gtmp = pgv.AGraph('file.dot')
G = nx.Graph(Gtmp)
nx.draw(G)
plt.show()
So now you have more options :)

Categories

Resources