How to add permanent name labels (not interactive ones) on nodes for a networkx graph in bokeh?

I am trying to add a permanent label on nodes for a networkx graph using spring_layout and bokeh library. I would like for this labels to be re-positioned as the graph scales or refreshed like what string layout does, re-positioning the nodes as the graph scales or refreshed.

I tried to create the graph, and layout, then got pos from the string_layout. However, as I call pos=nx.spring_layout(G), it will generated a set of positions for the nodes in graph G, which I can get coordinates of to put into the LabelSet. However, I have to call graph = from_networkx(G, spring_layout, scale=2, center=(0,0)) to draw the network graph. This will create a new set of position for the node. Therefore, the positions of the nodes and the labels will not be the same.

How to fix this issues?


Thanks for asking this question. Working through it, I've realized that it is currently more work than it should be. I'd very strongly encourage you to open a GitHub issue so that we can discuss what improvements can best make this kind of thing easier for users.

Here is a complete example:

import networkx as nx from bokeh.io import output_file, show from bokeh.models import CustomJSTransform, LabelSet from bokeh.models.graphs import from_networkx from bokeh.plotting import figure G=nx.karate_club_graph() p = figure(x_range=(-3,3), y_range=(-3,3)) p.grid.grid_line_color = None r = from_networkx(G, nx.spring_layout, scale=3, center=(0,0)) r.node_renderer.glyph.size=15 r.edge_renderer.glyph.line_alpha=0.2 p.renderers.append(r)

So far this is all fairly normal Bokeh graph layout code. Here is the additional part you need to add permanent labels for each node:

from bokeh.transform import transform # add the labels to the node renderer data source source = r.node_renderer.data_source source.data['names'] = [str(x*10) for x in source.data['index']] # create a transform that can extract the actual x,y positions code = """ var result = new Float64Array(xs.length) for (var i = 0; i < xs.length; i++) { result[i] = provider.graph_layout[xs[i]][%s] } return result """ xcoord = CustomJSTransform(v_func=code % "0", args=dict(provider=r.layout_provider)) ycoord = CustomJSTransform(v_func=code % "1", args=dict(provider=r.layout_provider)) # Use the transforms to supply coords to a LabelSet labels = LabelSet(x=transform('index', xcoord), y=transform('index', ycoord), text='names', text_font_size="12px", x_offset=5, y_offset=5, source=source, render_mode='canvas') p.add_layout(labels) show(p)

Basically, since Bokeh (potentially) computes layouts in the browser, the actual node locations are only available via the "layout provider" which is currently a bit tedious to access. As I said, please open a GitHub issue to suggest making this better for users. There are probably some very quick and easy things we can do to make this much simpler for users.

The code above results in:

<img src=https://www.e-learn.cn/content/wangluowenzhang/"https://i.stack.imgur.com/X9rdT.png" alt="enter image description here">


Fixed node positions

From the networkx.spring_layout() documentation: you can add a list of nodes with a fixed position as a parameter.

import networkx as nx import matplotlib.pyplot as plt g = nx.Graph() g.add_edges_from([(0,1),(1,2),(0,2),(1,3)]) pos = nx.spring_layout(g) nx.draw(g,pos) plt.show()

<img src=https://www.e-learn.cn/content/wangluowenzhang/"https://i.stack.imgur.com/sPL4R.png" alt="initial_graph">

Then you can plot the nodes at a fixed position:

pos = nx.spring_layout(g, pos=pos, fixed=[0,1,2,3]) nx.draw(g,pos) plt.show()

<img src=https://www.e-learn.cn/content/wangluowenzhang/"https://i.stack.imgur.com/bfJVn.png" alt="fixed_nodes">


  • adding layout to tabs on bokeh dashboard
  • Pagination in jsp using jQuery is not working
  • Lining up labels with the nodes on a Bokeh figure generated from a NetworkX graph
  • Html template formatter not working
  • How to run a Scrapy scraper multiple times, simultaneously, on different input websites and write to
  • how to write to new files sequentially
  • Bokeh multi_line and HoverTool
  • Object vs Extend in Java
  • Cancel current/active query in Ruby on Rails
  • Bokeh, combination of bar and line chart
  • Chrome native messaging: can I stream a MediaStream to a native program?
  • Setting the PixelFormat
  • Using VBA to Paste Excel Chart with Data into PowerPoint
  • How To retrieve a control in a Master Page from Content Page
  • Synchronous XHR deprecation
  • Play HTML audio in Internet Explorer?
  • ViewData, ViewBag and TempData violates MVC? [closed]
  • Exception handling as per java coding standards
  • Getting EOFError along with exceptions when using ftplib
  • Whats the right place for testhelper-classes? (phpunit/best practise)
  • insert a picture into database(sqlite) with java code. what should i do?
  • SQL query to group by maximal sets of a column having inner consecutive distances below a threshold
  • Getting error java.io.FileNotFoundException (log4j log file) at the time of publish project on cloud
  • Magento get URL before current
  • NHibernate manually control fetching
  • Prevent Tomcat from caching request during starup
  • How do I signal completion of my dataflow?
  • Calling Worksheet functions from vba in foreign language versions of Excel
  • How to use JavaScript to determine whether a file exists in a directory?
  • Yii2: Config params vs. const/define
  • Ajax Loaded meta Tags
  • How to make a tree having multiple type of nodes and each node can have multiple child nodes in java
  • Cassandra Data Model
  • Why winpcap requires both .lib and .dll to run?
  • Return words with double consecutive letters
  • Python: how to group similar lists together in a list of lists?
  • KeystoneJS: Relationships in Admin UI not updating
  • Codeigniter doesn't let me update entry, because some fields must be unique
  • Busy indicator not showing up in wpf window [duplicate]
  • How to get NHibernate ISession to cache entity not retrieved by primary key