简体   繁体   中英

Lining up labels with the nodes on a Bokeh figure generated from a NetworkX graph

I am trying to annotate a network graph which comes from NetworkX and which is visualised in Bokeh. I was able to successfully add the labels to the ColumnDataSource, and have them appear on the figure, but the coordinates appear to be wrong as the labels are not lined up with the nodes. Any help would be greatly appreciated.

from bokeh.io import show
from bokeh.plotting import figure
from bokeh.models.graphs import from_networkx
from bokeh.models import ColumnDataSource, LabelSet


def visualise_graph(G):
    plot = figure(title="Title", tools="", x_range=(-1.5, 1.5),
              y_range=(-1.5, 1.5), toolbar_location=None)
    graph = from_networkx(G, nx.spring_layout)
    plot.renderers.append(graph)
    return plot


def prepare_labels(G, plot):
    pos = nx.spring_layout(G)
    x, y = zip(*pos.values())
    node_labels = nx.get_node_attributes(N, 'label')
    source = ColumnDataSource({'x': x, 'y': y,
                               'label': [node_labels[i] for i in range(len(x))]})
    labels = LabelSet(x='x', y='y', text='label', source=source,
                      background_fill_color='white')
    plot.renderers.append(labels)
    return plot

 plot = visualise_graph(N)
 plot_w_labels = prepare_labels(N, plot)
 show(plot_w_labels)

I discovered the problem which was that I was using nx.spring_layout() to get the coordinates which actually generates a new graph with new coordinates. Instead I pulled the coordinates from the Bokeh figure using .layout_provider.graph_layout and it now works as desired.

My first ever post in stackoverflow so dont shoot me. Required change is smthg like this:

#draw graph with some layout
graph_renderer = from_networkx(graph_to_plot, nx.fruchterman_reingold_layout(graph_to_plot), scale=1, center=(0, 0))    
#x, y = zip(*pos.values())
x,y=zip(*graph_renderer.layout_provider.graph_layout.values())
graph_renderer.node_renderer.data_source.data['x']=x
graph_renderer.node_renderer.data_source.data['y']=y
.
.
label=LabelSet(x='x', y='y', text='index',level='glyph', source=graph_renderer.node_renderer.data_source)

@user2892709 - This is for you.

First, extract the coordinates for the nodes using graph_renderer.layout_provider.graph_layout

graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))

pos = graph_renderer.layout_provider.graph_layout
x,y=zip(*pos.values())

Then add those values to LabelSet()

source = ColumnDataSource({'x':x,'y':y, 'field': <your_node_list>})
labels = LabelSet(x='x', y='y', text='field', source=source)

Finally, you can add the values to the graph using:

plot.renderers.append(graph_renderer)
plot.renderers.append(labels)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM