我正在尝试使用spring_layout和散景库在nodex图表的节点上添加永久标签。我希望重新定位此标签,因为图形会像字符串布局那样缩放或刷新,在图形缩放或刷新时重新定位节点。
我尝试创建图形和布局,然后从string_layout获取pos。但是,当我调用# Generate polar and cartesian meshgrids
r = df_polar.columns
theta = df_polar.index
theta = np.deg2rad(theta)
# Polar meshgrid
rad_c, theta_c = np.meshgrid(r,theta)
# Cartesian meshgrid
X = rad_c * np.cos(theta_c)
Y = rad_c * np.sin(theta_c)
x,y = np.meshgrid(X,Y)
# Interpolate from polar to cartesian grid
new_grid = scipy.interpolate.griddata(
(rad_c.flatten(), theta_c.flatten()),
np.array(df_polar).flatten(), (x,y), method='nearest')
时,它将为图G中的节点生成一组位置,我可以获得放入LabelSet的坐标。但是,我必须致电catdatas = CarsDataset.query.all()
locations = [d.serializer() for d in catdatas]
carmap = Map(
identifier="carmap",
style="height:500px;width:500px;margin:0;",
lat=locations[0]['lat'],
lng=locations[0]['lng'],
markers=[(loc['lat'], loc['lng']) for loc in locations]
)
来绘制网络图。这将为节点创建一组新位置。因此,节点和标签的位置将不相同。
如何解决这个问题?
答案 0 :(得分:1)
感谢您提出这个问题。通过它,我意识到它目前的工作量应该超出应有的水平。我非常强烈建议您打开GitHub issue,以便我们可以讨论哪些改进最能让用户更容易做到这一点。
这是一个完整的例子:
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
# add the labels to the node renderer data source
source = r.node_renderer.data_source
source.data['names'] = [str(x*10) for x in source.data['index']]
# create a transform that can extract the actual x,y positions
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))
# Use the transforms to supply coords to a LabelSet
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(可能)在浏览器中计算布局,实际的节点位置只能通过&#34;布局提供商&#34;这访问目前有点乏味。正如我所说,请打开一个GitHub问题,建议让用户更好。我们可以做一些非常快速和简单的事情来使用户更加简单。
上面的代码导致:
答案 1 :(得分:-1)
从networkx.spring_layout()
文档:您可以添加一个固定位置的节点列表作为参数。
import networkx as nx
import matplotlib.pyplot as plt
g = nx.Graph()
g.add_edges_from([(0,1),(1,2),(0,2),(1,3)])
pos = nx.spring_layout(g)
nx.draw(g,pos)
plt.show()
然后您可以在固定位置绘制节点:
pos = nx.spring_layout(g, pos=pos, fixed=[0,1,2,3])
nx.draw(g,pos)
plt.show()
答案 2 :(得分:-1)
与@bigreddot类似的解决方案。
#Libraries for this solution
from bokeh.plotting import figure ColumnDataSource
from bokeh.models import LabelSet
#Remove randomness
import numpy as np
np.random.seed(1337)
#Load positions
pos = nx.spring_layout(G)
#Dict to df
labels_df = pd.DataFrame.from_dict(pos).T
#Reset index + column names
labels_df = labels_df.reset_index()
labels_df.columns = ["names", "x", "y"]
graph_renderer = from_networkx(G, pos, center=(0,0))
.
.
.
plot.renderers.append(graph_renderer)
#Set labels
labels = LabelSet(x='x', y='y', text='names', source=ColumnDataSource(labels_df))
#Add labels
plot.add_layout(labels)