如何将节点属性从NetworkX传递到bokeh [英] How to pass node attributes from NetworkX to bokeh
问题描述
我正在寻找一种将在NetworkX节点构造中确定的颜色传递给Bokeh图的方法.
有很多很棒的方法可以在散景图生成后在Bokeh图中实现颜色,例如
-
我不太了解如何使用bokeh的from_networkx函数获取这些值.看来这并没有像预期的那样传递属性.实际传递的是什么,我该如何传递颜色?
-
是否有更好的方法通过构造的ColumnDataSource分配更多属性?我在想类似于将其传递到数据框,添加颜色列,然后重新生成ColumnDataSource的方法,因此我可以为每个节点值使用'@node_color'检索颜色.
-
我有每个数据集的列表,因此可以通过某种方式进行过滤,例如:
如果list1中的node_id:node_color =红色"node_size = 10如果list2中的node_id:node_color =蓝色"node_size = 20
我对bokeh还是很陌生,尽管看起来这些应该是简单的任务,但是我完全迷失了文档.仅使用散景来生成网络可能会更好吗?
也许这个问题的答案可以帮助您: https://stackoverflow.com/a/54475870/8123623
创建一个dict,其中节点是键,颜色是值.
colors = [...]颜色= dict(zip(network.nodes,colors))nx.set_node_attributes(network,{k:v for colors中的k,v,colors.items()},'colors')graph.node_renderer.glyph =圆(大小= 5,fill_color ='颜色')
这是使用from_network()的方式
graph = from_networkx(G,nx.dot,scale = 1,center =(0,0))
I am looking for a way to pass a color, as assinged in NetworkX's node construction, to a Bokeh plot.
There are some great ways to implement color in the Bokeh plot after it is generated, such as this, but this solution requires that I apply the transformation to the entire data set based on an attribute.
I wanted to do something even simpler and assign a color and size based on what I assign those to be in NetworkX. I normally plot node set 1 as red, then node set 2 as blue in NetworkX, then connect them through their mutual edges. While the colors and size of the nodes are not passed to matplotlib, it IS passed to gephi when I save the file as graphml, so these data are somewhere..
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)
When opened in gephi, color is retained:
I can't quite understand how to fetch these values using bokeh's from_networkx function. It seems that this doesn't pass the attributes over as expected. What is actually being passed and how would I pass color?
Is there a better way to just assign more attributes through the ColumnDataSource that is constructed? I'm thinking something akin to passing it to a dataframe, adding a color column, then re-generating the ColumnDataSource, so I can retrieve the colors with '@node_color' for each node value.
I have lists of each of these datasets, so would it be possible to filter somehow such as:
if node_id in list1: node_color = "red" node_size = 10 if node_id in list2: node_color = "blue" node_size = 20
I'm very new to bokeh, and although it seems like these should be easy tasks, I'm completely lost in the documentation. Is it perhaps better to just generate a network using purely bokeh?
Maybe the answers under this question can help you: https://stackoverflow.com/a/54475870/8123623
Create a dict where the nodes are the keys and the colors the values.
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')
This is how you can use from_network()
graph = from_networkx(G, nx.dot, scale=1, center=(0,0))
这篇关于如何将节点属性从NetworkX传递到bokeh的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!