Как установить размер и цвет узла в сетевом графике боке?

Если мы возьмем стандартный пример клуба каратэ, как мне изменить цвет и размер узлов в соответствии с их степенью?

import networkx as nx

from bokeh.io import show, output_file
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

G=nx.karate_club_graph()

plot = Plot(plot_width=400, plot_height=400,
            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.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)

output_file("interactive_graphs.html")
show(plot)

введите описание изображения здесь

Я попытался сохранить градусы узлов в списке и ввести этот список в средство визуализации графа, но получил следующую ошибку:

# adjust node size according to degree, etc
d = nx.degree(G)
node_sizes = []
for i in d:
    _, value = i
    node_sizes.append(5*value)
...
graph_renderer.node_renderer.glyph = Circle(size=node_sizes, fill_color=Spectral4[0])

>>> ValueError: expected an element of either String, Dict(Enum('expr', 'field', 'value', 'transform', 'units'), Either(String, Instance(Transform), Instance(Expression), Float)) or Float, got <the list>

И для цвета я попытался заменить эту строку:

graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])

с этой строки

from bokeh.transform import linear_cmap
graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=linear_cmap('name', 'Spectral8', min(G.nodes()), max(G.nodes())))

Но это дает следующую ошибку:

ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: name [renderer: GlyphRenderer(id='ca38c587-0e5e-4bcb-a433-85602d3f66ab', ...)]
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: name [renderer: GlyphRenderer(id='def645fc-ecae-41b1-94e0-2baec74976f5', ...)]
ERROR:bokeh.core.validation.check:E-1010 (CDSVIEW_SOURCE_DOESNT_MATCH): CDSView used by Glyph renderer must have a source that matches the Glyph renderer's data source: GlyphRenderer(id='ac3d58b0-7a97-43c1-bfce-8e99b4286fa5', ...)
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: name [renderer: GlyphRenderer(id=༾b10671-1446-452b-81a9-9ba34dab2317', ...)]
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: name [renderer: GlyphRenderer(id=ེaa25ea-25a6-45ec-9931-25eca9870d6a', ...)]
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: name [renderer: GlyphRenderer(id=�c7-3e97-4c25-8418-5a916f18a6c4', ...)]
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: OWNER_CLIENT_NO [renderer: GlyphRenderer(id=Ɖfbaedfd-f2d9-48ea-bf7b-e86868c8438b', ...)]
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME): Glyph refers to nonexistent column name: name [renderer: GlyphRenderer(id='ca38c587-0e5e-4bcb-a433-85602d3f66ab', ...)]

и производит пустой HTML.

РЕДАКТИРОВАТЬ: я понял, как покрасить узлы.

# add different colors for each node
graph_renderer.node_renderer.data_source.data['color'] = list(G.nodes)

graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=linear_cmap('color', 'Spectral8', min(G.nodes), max(G.nodes)))

Это производит:

введите описание изображения здесь

Итак, теперь мне нужно только выяснить, как изменить размеры узла.

Всего 1 ответ


Вы делаете все правильно почти :)

Вместо ручного создания списка, вы должны создать data_source для рендерера и использовать его имя для автоматического выбора атрибутов (другая часть моего кода находится в вашем

gr = from_networkx(
    G,
    nx.circular_layout,
    scale=1,
    center=(0,0)
)
gr.node_renderer.data_source.data['index'] = list(reversed(range(len(G))))
gr.node_renderer.data_source.data['colors'] = Spectral8

gr.node_renderer.glyph = Circle(
    size='index',
    fill_color='colors'
)

нарисует вас:

введите описание изображения здесь


Есть идеи?

10000