Making networkx plot where edges only display edited numeric value, not field name

3.3k views Asked by At

The labels for the fields are displayed. You can see metric and weight

I want to make it so I can put a $ on the weight number and set it as the edge text. Can someone smart tell me the trick to do this? For example if the weight of an edge is 20, I want the edge text to be "$20"

Here is my code.

import json
import networkx as nx
import matplotlib.pyplot as plt
import os
import random
from networkx import graphviz_layout

G=nx.Graph()


for fn in os.listdir(os.getcwd()):
    with open(fn) as data_file:    
        data = json.load(data_file)
        name=data["name"]
        name=name.split(',')
        name = name[1] +  " " + name[0]
        cycle=data["cycle"]
        contributions=data["contributions"]
        contributionListforIndustry=[]
        colorList=[]
        colorList.append((random.uniform(0,1),random.uniform(0,1),random.uniform(0,1)))

        for contibution in contributions:
            amount=contibution["amount"]
            industryName=contibution["name"]
            metric=contibution["metric"]
            colorList.append((random.uniform(0,1),random.uniform(0,1),random.uniform(0,1)))
            contributionListforIndustry.append((industryName,amount))
            G.add_edge(name,industryName,weight=amount, metricval=metric)
        position=nx.graphviz_layout(G,prog='twopi',args='')
        nx.draw(G,position,with_labels=False,node_color=colorList )


        for p in position:  # raise text positions
                t= list(position[p])
                t[1]=t[1]+10
                position[p]=tuple(t)
        nx.draw_networkx_edge_labels(G,position)
        nx.draw_networkx_labels(G, position)
        plt.title("Break down for donations to " + name + " from agriculture industry for " +  str(cycle)  )
        plt.show()

Also if someone could tell me how I can make text appear to be in front of the plot, I.E the text is not being visually sliced by the edges, the edge text is on top of the edge if it should pass it. Lastly, for some reason the title of my plot isn't showing up. If someone knew a solution for that also it would be awesome. Thanks guys. Always a big help.

1

There are 1 answers

4
hitzg On BEST ANSWER

The documentation outlines that you have to use the edge_labels argument to specify custom labels. By default it the string representation of the edge data is used. In the example below such a dictionary is created: It has the edge tuples as keys and the formatted strings as values.

To make the node labels stand out more you can add a bounding box to the corresponding text elements. You can do that after draw_networkx_labels has created them:

import matplotlib.pyplot as plt
import networkx as nx

# Define a graph
G = nx.Graph()
G.add_edges_from([(1,2,{'weight':10, 'val':0.1}),
                  (1,4,{'weight':30, 'val':0.3}),
                  (2,3,{'weight':50, 'val':0.5}),
                  (2,4,{'weight':60, 'val':0.6}),
                  (3,4,{'weight':80, 'val':0.8})])
# generate positions for the nodes
pos = nx.spring_layout(G, weight=None)

# create the dictionary with the formatted labels
edge_labels = {i[0:2]:'${}'.format(i[2]['weight']) for i in G.edges(data=True)}

# create some longer node labels
node_labels = {n:"this is node {}".format(n) for n in range(1,5)}


# draw the graph
nx.draw_networkx(G, pos=pos, with_labels=False)

# draw the custom node labels
shifted_pos = {k:[v[0],v[1]+.04] for k,v in pos.iteritems()}
node_label_handles = nx.draw_networkx_labels(G, pos=shifted_pos,
        labels=node_labels)

# add a white bounding box behind the node labels
[label.set_bbox(dict(facecolor='white', edgecolor='none')) for label in
        node_label_handles.values()]

# add the custom egde labels
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=edge_labels)

plt.show()

EDIT:

You can't really remove the axes as they are the container for the entire graph. So what people usually do is to make the spines invisible:

# Axes settings (make the spines invisible, remove all ticks and set title)
ax = plt.gca()
[sp.set_visible(False) for sp in ax.spines.values()]
ax.set_xticks([])
ax.set_yticks([])

Setting the title should be straightforward:

ax.set_title('This is a nice figure')
# or 
plt.title('This is a nice figure')

Result: enter image description here