3

I am using networkX to draw a network plot from a distance matrix(emoji_sim, a DataFrame). Here is the code:

G = nx.from_numpy_matrix(np.array(emoji_sim))
nx.draw(G, edge_color='silver', node_color='lightsalmon', with_labels=True)
plt.show()

I know there is a way to relabel the nodes as:

G = nx.relabel_nodes(G, dict(zip(range(len(G.nodes())), range(1, len(G.nodes())+1))))   

But I want to substitute the nodes label with images(possibly read from files or using Python Emoji package). Is there any way to do that? Thanks a lot!

To clarify, I am trying to substitute the actual circle with images.

Vicky
  • 1,465
  • 2
  • 12
  • 21
  • Do you want the label to change, or the actual circle that's plotted for the node to change? – Joel Oct 17 '15 at 20:53
  • Thanks for the question. I am trying to change the circle to images. – Vicky Oct 17 '15 at 21:29
  • 1
    I don't think it's built in, but I don't think it's incredibly hard. I don't have time to work up the whole solution, but here is a hint that hopefully will lead someone else to fill in details: you can use networkx to get the node positions. Then use matplotlib to plot the images at those positions. Then draw the edges. – Joel Oct 17 '15 at 22:07

1 Answers1

7

The idea behind it is not very difficult but in order to get it to be displayed (at least on ubunto) it gave me some hard time as not all fonts support emoji. I shall display the straight forward way then some links that helped me in the end (maybe you will not need those).

From emoji cheat sheet from the emoji python package I picked up three to be shown as an example and here is the code.

G = nx.Graph()
G.add_nodes_from([0,1,2])
n0 = emoji.emojize(':thumbsup:',use_aliases=True)
n1 = emoji.emojize(':sob:',use_aliases=True)
n2 = emoji.emojize(':joy:',use_aliases=True)
labels ={0:n0,1:n1,2:n2}
nx.draw_networkx(G,labels=labels, node_color = 'w', linewidths=0, with_labels=True, font_family = 'Symbola' ,font_size = 35)    
plt.show()

enter image description here

Difficulties encountered:

1- My machine is on ubunto 14.04, I could not display any emoji they always appeared as rectangles

Installed needed font Symbola using the following command (mentioned here):

sudo apt-get install ttf-ancient-fonts

2- Maplotlib (which networkx calls to draw) is not using the installed font.

From several useful discussions 1 2 3 4 5 6 I copied and pasted the .tff font file of Symbola in the default matplotib directory (where it fetches for fonts to use).

cp /usr/share/fonts/truetype/ttf-ancient-scripts/Symbola605.ttf /usr/share/matplotlib/mpl-data/fonts/ttf

Then I had to delete fontList.cache file for the new font to be loaded.

rm ~/.cache/matplotlib/fontList.cache

Note

You can have different views by changing the input to the draw_networkx e.g. not sending the linewidths will show circular border for each node, also if you want a specific background color for nodes change the color_node from white to a color that you want ... for more details check the documentation.

Community
  • 1
  • 1
Abdallah Sobehy
  • 2,881
  • 1
  • 15
  • 28
  • Take a look at `nx.draw_networkx_labels` ([documentation](https://networkx.github.io/documentation/latest/reference/generated/networkx.drawing.nx_pylab.draw_networkx_labels.html)) and also it's usually better to predefine the position `pos` with `pos=nx.spring_layout(G)` or some other preferred layout. This let's you do multiple things to a plot without it changing the locations of the nodes. – Joel Oct 19 '15 at 00:53
  • 1
    Each time `spring_layout` runs, it starts from a random initial condition. So if you want to do multiple colors, or put some nodes on top of others, or just do anything that would involve calling more than one plot command, the whole network will be repositioned. So you're right it's not necessary in this case, but for most elaborate things you might try, it's useful. Since you had set the linewidth to zero and node color to white rather than just drawing the label, it looked like you weren't as experienced with the networkx drawing commands as other parts. I thought I'd mention it as well. – Joel Oct 19 '15 at 01:08
  • Ah it is clearer now, thanks for the hint. I shall take it into consideration from now on. – Abdallah Sobehy Oct 19 '15 at 01:10
  • I suppose also here if I had edges they would not appear. Which would prove to be more important to draw labels separately. EDIT Actually I have tried but the edges appear even if the linewidths is set to zero. – Abdallah Sobehy Oct 19 '15 at 01:12