web-dev-qa-db-fra.com

Ajout d'étiquettes de noeuds aux tracés réseau bokeh

J'utilise le code suivant pour produire un graphe de réseau bokeh interactif. Comment ajouter le nom des noeuds aux noeuds du graphique de bokeh? 

from bokeh.io import show, output_notebook
from bokeh.models import Plot, Range1d, MultiLine, Circle, HoverTool, TapTool, BoxSelectTool
from bokeh.models.graphs import from_networkx, NodesAndLinkedEdges, EdgesAndLinkedNodes
from bokeh.palettes import Spectral4
from bokeh.models import LabelSet

plot = Plot(plot_width=900, plot_height=500,
            x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
plot.title.text = "Graph Interaction Demonstration"

plot.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool())

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

graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])
graph_renderer.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2])
graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1])
graph_renderer.node_renderer.glyph.properties_with_values()
graph_renderer.Edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5)
graph_renderer.Edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=5)
graph_renderer.Edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)

graph_renderer.selection_policy = NodesAndLinkedEdges()
graph_renderer.inspection_policy = EdgesAndLinkedNodes()

plot.renderers.append(graph_renderer)

show(plot)

graphe réseaux de bokeh résultant:  enter image description here

8
Kate Lewis

Je suppose que vous voulez dire des étiquettes interactives pour les nœuds, quelque chose que je voulais aussi faire. Pour ce faire, vous devez modifier quelques lignes:

hover = HoverTool(tooltips=[("Name:", "@name")])
plot.add_tools(hover, TapTool(), BoxSelectTool(), WheelZoomTool())
...
graph_renderer.inspection_policy = NodesAndLinkedEdges()

Puis modifiez la source de données pour les nœuds:

graph_renderer.node_renderer.data_source.data['name'] = [name1, ... ,nameN]

(la source de données existe déjà; il s'agit d'un dictionnaire dont la seule clé est 'index', une liste numérotée de nœuds. Vous pouvez ainsi ajouter d'autres clés référençant des listes de même longueur, telles qu'une liste de noms, et ces listes peut être consulté via '@key')

7
Paddy Alton

Sujet brûlant!! Je pense que je viens de le recevoir. Ils ont peut-être plus de manières pythoniques, mais ce que j’ai fait était 

  1. Créer une source de données avec les étiquettes appropriées
  2. Récupérer des positions du graphique en utilisant pos = nx.circular_layout (G)
  3. ajouter ces positions à mon source de données
  4. Créer un LabelSet à partir des positions et de la source

Leonardo, vous manquez la ligne où G est créé. J'ai pris le karate_club_graph et cela fonctionne pour moi:

from bokeh.models import ColumnDataSource
pos = nx.circular_layout(G)
x,y=Zip(*pos.values())

source = ColumnDataSource({'x':x,'y':y,'kid':['Joe %d' %ix for ix in range(len(x))]})
labels = LabelSet(x='x', y='y', text='kid', source=source)

plot.renderers.append(labels)
1
Sergio Lucero

J'ai trouvé la réponse de @ SergioLucero trop incomplète pour répondre à la question, l'exemple de code ne fonctionnant pas.

Cependant, avec le code et la réponse créés par @ifearthenight (d'après cette question: Aligner les étiquettes avec les nœuds d'une figure de Bokeh générés à partir d'un graphe NetworkX ), j'ai pu produire un exemple de travail.

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

G = nx.karate_club_graph()

plot = figure(title="Karate Club Graph", 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)

x, y = Zip(*graph.layout_provider.graph_layout.values())
node_labels = nx.get_node_attributes(G, 'club')
source = ColumnDataSource({'x': x, 'y': y,
                           'club': [node_labels[i] for i in range(len(x))]})
labels = LabelSet(x='x', y='y', text='club', source=source,
                  background_fill_color='white')

plot.renderers.append(labels)
show(plot)
1
Tom Hemmes