感谢您提出这个问题。在解决它的过程中,我意识到目前要做的事情比应该做的要多。我强烈建议您打开
GitHub问题,以便我们可以讨论如何改进,使这种操作更容易为用户所用。
下面是一个完整的示例:
import networkx as nx
from bokeh.io import output_file, show
from bokeh.models import CustomJSTransform, LabelSet
from bokeh.models.graphs import from_networkx
from bokeh.plotting import figure
G=nx.karate_club_graph()
p = figure(x_range=(-3,3), y_range=(-3,3))
p.grid.grid_line_color = None
r = from_networkx(G, nx.spring_layout, scale=3, center=(0,0))
r.node_renderer.glyph.size=15
r.edge_renderer.glyph.line_alpha=0.2
p.renderers.append(r)
到目前为止,这些都是Bokeh图形布局代码中比较常见的内容。下面是你需要添加每个节点永久标签的附加部分:
from bokeh.transform import transform
source = r.node_renderer.data_source
source.data['names'] = [str(x*10) for x in source.data['index']]
code = """
var result = new Float64Array(xs.length)
for (var i = 0; i < xs.length; i++) {
result[i] = provider.graph_layout[xs[i]][%s]
}
return result
"""
xcoord = CustomJSTransform(v_func=code % "0", args=dict(provider=r.layout_provider))
ycoord = CustomJSTransform(v_func=code % "1", args=dict(provider=r.layout_provider))
labels = LabelSet(x=transform('index', xcoord),
y=transform('index', ycoord),
text='names', text_font_size="12px",
x_offset=5, y_offset=5,
source=source, render_mode='canvas')
p.add_layout(labels)
show(p)
基本上,由于 Bokeh(可能)在浏览器中计算布局,因此实际节点位置仅通过“布局提供程序”可用,但目前访问起来有点麻烦。正如我所说,请打开一个 GitHub 问题建议为用户改进此功能。我们可能可以做一些非常快速和简单的事情,使用户更容易使用。
上面的代码结果如下:
nx
图生成静态布局,您也可以在Python中提取(x,y)
坐标,并将它们放入LabelSet
的数据源中。这将避免使用JS转换,但我认为上述方法是最通用和“正确”的方法。 - bigreddot