Bokehは、エッジとノードとの間の構成可能な相互作用を有するネットワークマップ可視化を作成するためのローカルサポートを増加させる。
主な機能は GraphRenderer これは,グラフノードとグラフエッジのための単独の子GlyphRendererを保持する.これはGraphRenenderの node_renderer 財産です。デフォルトのCircleノードフラグ記号、例えば、RECTまたはEllipseフラグ記号のようなデフォルトのCircleノードフラグ記号は、任意のXYGlyphインスタンスで置き換えることができる。同様に,辺のパターン属性も通過することができる edge_renderer 財産です。エッジフラグシンボルは、現在、複数行のフラグシンボルに限定されている。
GraphRenderer
node_renderer
edge_renderer
これらのサブレンダラに属するデータソースにはいくつかの要求があります:
節レンダラに関連するColumnDataSourceは名前の列を持たなければならない. "index" これはノードの一意のインデックスを含む.
"index"
エッジサブレンダラに関連するColumnDataSourceには2つの必要な列がある: "start" そして "end" それがそうです。これらの列は辺の始点と終点のノードインデックスを含む.
"start"
"end"
これらのデータソースに追加のメタデータを追加して、ベクトル化された字形パターンを追加するために、またはデータをコールバックまたはホバリングツール提示のために使用することができるようにすることができる。
以下は、以下のコードセグメントである。
ノードラベルを楕円に置き換える
設ける height そして width スカラー値である楕円の属性
height
width
設ける fill_color 属性はベクトル化フィールドとしてノードデータソースに値を追加する.
fill_color
import math from bokeh.plotting import figure from bokeh.models import GraphRenderer, Ellipse from bokeh.palettes import Spectral8 N = 8 node_indices = list(range(N)) plot = figure(title="Graph Layout Demonstration", x_range=(-1.1,1.1), y_range=(-1.1,1.1), tools="", toolbar_location=None) graph = GraphRenderer() graph.node_renderer.glyph = Ellipse(height=0.1, width=0.2, fill_color="fill_color") graph.node_renderer.data_source.data = dict( index=node_indices, fill_color=Spectral8) graph.edge_renderer.data_source.data = dict( start=[0]*N, end=node_indices)
上のコードセグメントを実行すると、2 D空間に図形をどのように配置するかは指定されていないので、グラフィックは何も表示されません。あなたは次の節でこれをする方法を知ることができる。
Bokehは単独のものを使用します LayoutProvider モデルは,デカルト空間において図形の座標を提供する.現在内蔵されている唯一の提供プログラムは StaticLayoutProvider モデルは,ノードの(x,y)座標辞書を含む.
LayoutProvider
StaticLayoutProvider
この例は、上記のコードセグメントにプログラムを追加する。
import math from bokeh.io import output_file, show from bokeh.models import Ellipse, GraphRenderer, StaticLayoutProvider from bokeh.palettes import Spectral8 from bokeh.plotting import figure N = 8 node_indices = list(range(N)) plot = figure(title='Graph Layout Demonstration', x_range=(-1.1,1.1), y_range=(-1.1,1.1), tools='', toolbar_location=None) graph = GraphRenderer() graph.node_renderer.data_source.add(node_indices, 'index') graph.node_renderer.data_source.add(Spectral8, 'color') graph.node_renderer.glyph = Ellipse(height=0.1, width=0.2, fill_color='color') graph.edge_renderer.data_source.data = dict( start=[0]*N, end=node_indices) ### start of layout code circ = [i*2*math.pi/8 for i in node_indices] x = [math.cos(i) for i in circ] y = [math.sin(i) for i in circ] graph_layout = dict(zip(node_indices, zip(x, y))) graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) plot.renderers.append(graph) output_file('graph.html') show(plot)
デフォルトの場合、 StaticLayoutProvider 提供されたノード位置の間に直線経路が描画される。明示的なエッジ経路を提供するために、ルーティングテーブルをルーティングテーブルに提供することもできる edge_renderer bokeh.models.sources.ColumnDataSource それがそうです。♪the StaticLayoutProvider あるだろう "xs" そして "ys" データソース列。これらの経路の順序は "start" そして "end" ポイント。なお,それらがノード位置と一致するかどうかは検証されていないため,明示的な経路を設定する際には特に注意が必要である.
bokeh.models.sources.ColumnDataSource
"xs"
"ys"
この例は、ノード間で二次Bezier経路を描画するために、上記の例を拡張する。
import math from bokeh.io import output_file, show from bokeh.models import Ellipse, GraphRenderer, StaticLayoutProvider from bokeh.palettes import Spectral8 from bokeh.plotting import figure N = 8 node_indices = list(range(N)) plot = figure(title="Graph Layout Demonstration", x_range=(-1.1,1.1), y_range=(-1.1,1.1), tools="", toolbar_location=None) graph = GraphRenderer() graph.node_renderer.data_source.add(node_indices, 'index') graph.node_renderer.data_source.add(Spectral8, 'color') graph.node_renderer.glyph = Ellipse(height=0.1, width=0.2, fill_color="color") graph.edge_renderer.data_source.data = dict( start=[0]*N, end=node_indices) ### start of layout code circ = [i*2*math.pi/8 for i in node_indices] x = [math.cos(i) for i in circ] y = [math.sin(i) for i in circ] graph_layout = dict(zip(node_indices, zip(x, y))) graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) ### Draw quadratic bezier paths def bezier(start, end, control, steps): return [(1-s)**2*start + 2*(1-s)*s*control + s**2*end for s in steps] xs, ys = [], [] sx, sy = graph_layout[0] steps = [i/100. for i in range(100)] for node_index in node_indices: ex, ey = graph_layout[node_index] xs.append(bezier(sx, ex, 0, steps)) ys.append(bezier(sy, ey, 0, steps)) graph.edge_renderer.data_source.data['xs'] = xs graph.edge_renderer.data_source.data['ys'] = ys plot.renderers.append(graph) output_file("graph.html") show(plot)
Bokehは、そのnetworkx統合を介して高速にネットワークマップを描画することをサポートしています。♪the bokeh.plotting.from_networkx 利便性受容 networkx.Graph オブジェクトとnetworkxレイアウト方法は,配置されたGraphRenenderのインスタンスを返す.
bokeh.plotting.from_networkx
networkx.Graph
次は使用します networkx.spring_layout Networkx内蔵の“Zacharyの空手クラブ図”データセットのレイアウト方法:
networkx.spring_layout
import networkx as nx from bokeh.io import output_file, show from bokeh.plotting import figure, from_networkx G = nx.karate_club_graph() plot = figure(title="Networkx Integration Demonstration", x_range=(-1.1,1.1), y_range=(-1.1,1.1), tools="", toolbar_location=None) graph = from_networkx(G, nx.spring_layout, scale=2, center=(0,0)) plot.renderers.append(graph) output_file("networkx_graph.html") show(plot)
GraphRenenderを設置することで selection_policy そして inspection_policy 属性です。これらの戦略属性は特殊な GraphHitTestPolicy モデル例。
selection_policy
inspection_policy
GraphHitTestPolicy
例えば、設定 selection_policy=NodesAndLinkedEdges() 選定されたノードにも関連するエッジを選択させる.同様に設定します inspection_policy=EdgesAndLinkedNodes() エッジの開始ノードと終了ノードをホバリングツールを用いてエッジをホバリングする際にも検査される.
selection_policy=NodesAndLinkedEdges()
inspection_policy=EdgesAndLinkedNodes()
Users may want to customize the selection_glyph, nonselection_glyph, and/or hover_glyph attributes of the edge and node sub-renderers in order to add dynamic visual elements to their graph interactions.
selection_glyph
nonselection_glyph
hover_glyph
以下は、ノードとエッジの相互作用を追加したグラフの例である。
import networkx as nx from bokeh.io import output_file, show from bokeh.models import (BoxSelectTool, Circle, EdgesAndLinkedNodes, HoverTool, MultiLine, NodesAndLinkedEdges, Plot, Range1d, TapTool,) from bokeh.palettes import Spectral4 from bokeh.plotting import from_networkx 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)
はい。 from_networkx, NetworkX's node/edge attributes are converted for GraphRenderer's node_renderer/edge_renderer それがそうです。
from_networkx
たとえば,“Zacharyの空手クラブ図”データセットには“Club”というノード属性がある.この情報は,中変換されたノード属性を用いてホバリングすることができる. from_networkx それがそうです。同様に、ノード/エッジ属性は、色情報にも使用されてもよい。
以下は、ノード属性をホバリングし、エッジ属性を使用して色を変更するグラフの例です。
import networkx as nx from bokeh.io import output_file, show from bokeh.models import (BoxZoomTool, Circle, HoverTool, MultiLine, Plot, Range1d, ResetTool,) from bokeh.palettes import Spectral4 from bokeh.plotting import from_networkx # Prepare Data G = nx.karate_club_graph() SAME_CLUB_COLOR, DIFFERENT_CLUB_COLOR = "black", "red" edge_attrs = {} for start_node, end_node, _ in G.edges(data=True): edge_color = SAME_CLUB_COLOR if G.nodes[start_node]["club"] == G.nodes[end_node]["club"] else DIFFERENT_CLUB_COLOR edge_attrs[(start_node, end_node)] = edge_color nx.set_edge_attributes(G, edge_attrs, "edge_color") # Show with Bokeh 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" node_hover_tool = HoverTool(tooltips=[("index", "@index"), ("club", "@club")]) plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool()) graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0]) graph_renderer.edge_renderer.glyph = MultiLine(line_color="edge_color", line_alpha=0.8, line_width=1) plot.renderers.append(graph_renderer) output_file("interactive_graphs.html") show(plot)