1

I am trying to plot a knowledge graph using Python, have looked at many examples and answers, but still did not manage to plot the edge labels automatically from an edgelist. Here is a reduced working example of what I am trying to do:

import pandas as pd
import networkx as nx
minidf = pd.DataFrame(data={'relation': ['subject', 'subject', 'broader'], 
                       'source': ['pmt3423', 'pmt2040', 'category:myoblasts'], 
                       'target': ['conceito', 'frio', 'category:non-terminally_differentiated_(blast)']})
miniG = nx.from_pandas_edgelist(minidf,'source', 'target',
                      edge_key='relation', create_using=nx.MultiDiGraph())
nx.draw_networkx(miniG, with_labels=True)

The output I get is the following:

Graph without labels

I have also tried draw_circular and others. I have also tried using pyvis and generating a dot file + converting to png using neato. Didn't quite get it yet. Any help is appreciated.

Sparky05
  • 4,692
  • 1
  • 10
  • 27
DSchlingel
  • 15
  • 7
  • Have you checked this question: https://stackoverflow.com/questions/32905262/how-do-i-draw-edge-labels-for-multigraph-in-networkx? [nx.draw_networkx_edge_labels](https://networkx.org/documentation/stable/reference/generated/networkx.drawing.nx_pylab.draw_networkx_edge_labels.html#networkx.drawing.nx_pylab.draw_networkx_edge_labels) does not seem to support MultiGraphs. – Sparky05 Aug 18 '21 at 09:33
  • Yes. I have tried that, but it does not work still. It seems like, somehow, my graph is not supported. Also, when I create the graph using edge_attr=True, or the column relation or even the list ['relation'], it runs but has no effect in adding the attributes to the edges. But thanks @Sparky05, I think I will drop this visualization for now. – DSchlingel Aug 18 '21 at 20:53
  • I just saw that in your given example no edge attributes are in the created graph. Not sure if this is an error in your minimal example (which is by the way very useful) or also in your general code, have a look at the examples in [from_pandas_edgelist](https://networkx.org/documentation/stable/reference/generated/networkx.convert_matrix.from_pandas_edgelist.html). If I understand the docs correctly you need for multigraphs `edge_key` and `edge_column`. – Sparky05 Aug 19 '21 at 07:23

1 Answers1

3

Here is how you can add edge labels to your graph:

import pandas as pd
import networkx as nx
from matplotlib import pyplot as plt

minidf = pd.DataFrame(data = {'relation': ['subject', 'subject', 'broader'],
                       'source': ['pmt3423', 'pmt2040', 'category:myoblasts'],
                       'target': ['conceito', 'frio', 'category:non-terminally_differentiated_(blast)']})

miniG = nx.from_pandas_edgelist(minidf,'source', 'target', create_using=nx.MultiDiGraph())

pos = nx.spring_layout(miniG)
e_labels = {(minidf.source[i], minidf.target[i]):minidf.relation[i]
          for i in range(len(minidf['relation']))}

nx.draw_networkx_edge_labels(miniG, pos, edge_labels= e_labels)
nx.draw(miniG, pos = pos,with_labels=True)
plt.show()

enter image description here

However, as you see above, this can be messy because there is not much room for edge labels in your graph. A better solution would be to color-code the edges and provide a legend:

import pandas as pd
import networkx as nx
from matplotlib import pyplot as plt

minidf = pd.DataFrame(data = {'relation': ['subject', 'subject', 'broader'],
                       'source': ['pmt3423', 'pmt2040', 'category:myoblasts'],
                       'target': ['conceito', 'frio', 'category:non-terminally_differentiated_(blast)']})

miniG = nx.from_pandas_edgelist(minidf,'source', 'target', create_using=nx.MultiDiGraph())

#color-code the edges
color_code = {'subject':'red', 'broader':'lime'}
edge_color_list = [color_code[rel] for rel in minidf.relation]
nx.draw(miniG, with_labels= True, edge_color= edge_color_list)

#create a color-coded legend
leg = plt.legend(color_code,labelcolor=color_code.values())
for i, item in enumerate(leg.legendHandles):
    item.set_color(list(color_code.values())[i])

plt.show()

enter image description here

pakpe
  • 5,391
  • 2
  • 8
  • 23