Как передать атрибуты узла из NetworkX в bokeh - PullRequest
0 голосов
/ 05 октября 2018

Я ищу способ передать цвет, как указано в конструкции узла NetworkX, на график Bokeh.

Существует несколько отличных способов реализовать цвет на графике Боке после его создания, например this , но это решение требует, чтобы я применил преобразование ко всему набору данных на основеприписывать.

Я хотел сделать что-то еще более простое и назначить цвет и размер в зависимости от того, что я назначил для них в NetworkX.Обычно я отображаю набор узлов 1 как красный, затем набор узлов 2 как синий в NetworkX, затем соединяю их через их взаимные края.Хотя цвета и размеры узлов не передаются в matplotlib, он IS передается в Gephi, когда я сохраняю файл как graphml, поэтому эти данные находятся где-то ..

import networkx as nx
from bokeh.io import show, output_file
from bokeh.plotting import figure,show
from bokeh.models.graphs import from_networkx #I haven't been able to use this!
from bokeh.io import output_notebook
from bokeh.models import HoverTool, ColumnDataSource
from bokeh.resources import CDN
from bokeh.embed import file_html

Dataset1 = ['A','B','C','D','E','F']
Dataset2 = ['ONE','TWO','THREE','FOUR','FIVE','TWENTY_EIGHT']
Edgelist = [('A','ONE'),('B','ONE'),('E','ONE'),('A','TWO'),('A','THREE'),('A','FOUR'),('C','THREE'),('D','FIVE'),('D',"TWENTY_EIGHT")]
G = nx.Graph()
G.add_nodes_from(Dataset1,color= 'green')  
G.add_nodes_from(Dataset2,color='blue') 
G.add_edges_from(Edgelist,weight=0.8)
layout = nx.draw_spring(G, with_labels=True)
nx.write_graphml(G,"TEST.graphML")
network = nx.read_graphml("TEST.graphML")

#start Bokeh code
layout = nx.spring_layout(network,k=1.1/sqrt(network.number_of_nodes()),iterations=100) #pass the NX file to a spring layout

nodes, nodes_coordinates = zip(*sorted(layout.items()))
nodes_xs, nodes_ys = list(zip(*nodes_coordinates))
nodes_source = ColumnDataSource(dict(x=nodes_xs, y=nodes_ys,name=nodes)) #Can this pass the color? 

hover = HoverTool(tooltips=[('name', '@name')]) #would like to know how to add in more values here manually

plot = figure(plot_width=800, plot_height=400,tools=['tap', hover, 'box_zoom', 'reset'])

r_circles = plot.circle('x', 'y', source=nodes_source, size=10, color='orange', level = 'overlay')#this function sets the color of the nodes, but how to set based on the name of the node? 


def get_edges_specs(_network, _layout): 
    d = dict(xs=[], ys=[], alphas=[])
    weights = [d['weight'] for u, v, d in _network.edges(data=True)]
    max_weight = max(weights)
    calc_alpha = lambda h: 0.1 + 0.6 * (h / max_weight)

    # example: { ..., ('user47', 'da_bjoerni', {'weight': 3}), ... }
    for u, v, data in _network.edges(data=True):
        d['xs'].append([_layout[u][0], _layout[v][0]])
        d['ys'].append([_layout[u][1], _layout[v][1]])
        d['alphas'].append(calc_alpha(data['weight']))
    return d

lines_source = ColumnDataSource(get_edges_specs(network, layout))

r_lines = plot.multi_line('xs', 'ys', line_width=1.5,
                      alpha='alphas', color='navy',
                      source=lines_source)#This function sets the color of the edges

show(plot)

КогдаОткрыт в Gephi, цвет сохраняется: From Gephi

  1. Я не совсем понимаю, как получить эти значения, используя функцию bokeh from_networkx.Кажется, что это не передает атрибуты, как ожидалось.Что на самом деле передается и как мне передать цвет?

  2. Есть ли лучший способ просто назначить больше атрибутов через созданный ColumnDataSource?Я думаю, что-то похожее на передачу этого в информационный фрейм, добавление цветного столбца, а затем повторную генерацию ColumnDataSource, чтобы я мог получить цвета с помощью @node_color для каждого значения узла.

  3. У меня есть списки каждого из этих наборов данных, поэтому можно ли их отфильтровать, например:

    if node_id in list1:
        node_color = "red"
        node_size = 10
    if node_id in list2:
        node_color = "blue"
        node_size = 20
    

I'mочень плохо знаком с боке, и, хотя кажется, что это должны быть простые задачи, я полностью потерялся в документации.Может быть, лучше просто создать сеть, используя чисто боке?

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Может быть, ответы на этот вопрос помогут вам: https://stackoverflow.com/a/54475870/8123623

Создайте подсказку, где узлы - это ключи, а цвета - значения.

colors = [...]
colors = dict(zip(network.nodes, colors))
nx.set_node_attributes(network, {k:v for k,v in colors.items()},'colors' )
graph.node_renderer.glyph = Circle(size=5, fill_color='colors')

Вот как выможно использовать from_network ()

graph = from_networkx(G, nx.dot, scale=1, center=(0,0))
0 голосов
/ 10 октября 2018

ПОЛУЧИЛ ЭТО

Атрибут цвета, который я видел у всех, задаваемых через различные атрибуты (например, степень центральности и т. Д.), Был создан через экземпляр цветовой карты, но этоНЕ требуется для установки наборов узлов в разные цвета или размеры.

Ключевым моментом здесь является способ создания ColumnDataSource (CDS).Используя строку:

nodes_source = ColumnDataSource(dict(x=nodes_xs, y=nodes_ys,name=nodes)

Нет назначения цвета или размера в качестве атрибута.Хуже того, я не смог увидеть, как CDS на самом деле выглядел .(Который я теперь знаю, вы можете просмотреть как DF-панда, вызвав CDS.to_df ()). Итак, я экспериментировал и обнаружил, что могу добавить столбец следующим образом:

node_color=pd.DataFrame.from_dict({k:v for k,v in network.nodes(data=True)},orient='index').color.tolist()
color = tuple(node_color)

nodes_source = ColumnDataSource(dict(x=nodes_xs, y=nodes_ys,name=nodes, _color_= color)

Это назначило атрибут, который яизвлекается из networkX в качестве значения для каждого узла в зависимости от его идентификатора, передает его в кортеж, затем помещает его в CDS, который будет извлечен путем запроса конструкции Bokeh для получения данных из столбца, имя которого передается как ** STRING **:

plot = figure(plot_width=800, plot_height=400,tools=['tap', hover, 'box_zoom', 'reset'])

r_circles = plot.circle('x', 'y', source=nodes_source, size=10,fill_color="_color_", level = 'overlay')

Чтобы ответить на все 3 вопроса:

  1. from_networkx извлекает все характеристики узлов, [по крайней мере], если получено через from_graphml() функция.

  2. Самый простой способ присвоить значение columndatavalue - передать ему кортеж, как показано выше, с атрибутом цвета.Тем не менее, именно здесь вы можете добавить в CDS вещи, которые вы можете извлечь из инструмента наведения мыши.Для меня это будет очень полезно.

  3. Создайте DF pandas со всеми необходимыми атрибутами, затем используйте функцию CDS.from_df (), чтобы передать ее в CDS для анализа bokeh.

...