我试图在 `networkx` 的边缘上绘制一个轮廓线 (`linestyle=":"`)。我似乎无法弄清如何对 `matplotlib` 的 `patch` 对象进行操作以绘制这些 "edges" 的轮廓线。如果这不可能,有人知道如何单独获取线数据并使用 `ax.plot(x, y, linestyle=":")` 来完成此操作吗?
import networkx as nx
import numpy as np
from collections import *
# Graph data
G = {'y1': OrderedDict([('y2', OrderedDict([('weight', 0.8688325076457851)])), (1, OrderedDict([('weight', 0.13116749235421485)]))]), 'y2': OrderedDict([('y3', OrderedDict([('weight', 0.29660515972204304)])), ('y4', OrderedDict([('weight', 0.703394840277957)]))]), 'y3': OrderedDict([(4, OrderedDict([('weight', 0.2858185316736193)])), ('y5', OrderedDict([('weight', 0.7141814683263807)]))]), 4: OrderedDict(), 'input': OrderedDict([('y1', OrderedDict([('weight', 1.0)]))]), 'y4': OrderedDict([(3, OrderedDict([('weight', 0.27847763084646443)])), (5, OrderedDict([('weight', 0.7215223691535356)]))]), 3: OrderedDict(), 5: OrderedDict(), 'y5': OrderedDict([(6, OrderedDict([('weight', 0.5733512797415756)])), (2, OrderedDict([('weight', 0.4266487202584244)]))]), 6: OrderedDict(), 1: OrderedDict(), 2: OrderedDict()}
G = nx.from_dict_of_dicts(G)
G_scaffold = {'input': OrderedDict([('y1', OrderedDict())]), 'y1': OrderedDict([('y2', OrderedDict()), (1, OrderedDict())]), 'y2': OrderedDict([('y3', OrderedDict()), ('y4', OrderedDict())]), 1: OrderedDict(), 'y3': OrderedDict([(4, OrderedDict()), ('y5', OrderedDict())]), 'y4': OrderedDict([(3, OrderedDict()), (5, OrderedDict())]), 4: OrderedDict(), 'y5': OrderedDict([(6, OrderedDict()), (2, OrderedDict())]), 3: OrderedDict(), 5: OrderedDict(), 6: OrderedDict(), 2: OrderedDict()}
G_scaffold = nx.from_dict_of_dicts(G_scaffold)
G_sem = {'y1': OrderedDict([('y2', OrderedDict([('weight', 0.046032370518141796)])), (1, OrderedDict([('weight', 0.046032370518141796)]))]), 'y2': OrderedDict([('y3', OrderedDict([('weight', 0.08764771571290508)])), ('y4', OrderedDict([('weight', 0.08764771571290508)]))]), 'y3': OrderedDict([(4, OrderedDict([('weight', 0.06045928834718992)])), ('y5', OrderedDict([('weight', 0.06045928834718992)]))]), 4: OrderedDict(), 'input': OrderedDict([('y1', OrderedDict([('weight', 0.0)]))]), 'y4': OrderedDict([(3, OrderedDict([('weight', 0.12254141747735424)])), (5, OrderedDict([('weight', 0.12254141747735425)]))]), 3: OrderedDict(), 5: OrderedDict(), 'y5': OrderedDict([(6, OrderedDict([('weight', 0.11700701511079069)])), (2, OrderedDict([('weight', 0.11700701511079069)]))]), 6: OrderedDict(), 1: OrderedDict(), 2: OrderedDict()}
G_sem = nx.from_dict_of_dicts(G_sem)
# Edge info
edge_input = ('input', 'y1')
weights_sem = np.array([G_sem[u][v]['weight']for u,v in G_sem.edges()]) * 256
# Layout
pos = nx.nx_agraph.graphviz_layout(G_scaffold, prog="dot", root="input")
# Plotting graph
pad = 10
with plt.style.context("ggplot"):
fig, ax = plt.subplots(figsize=(8,8))
linecollection = nx.draw_networkx_edges(G_sem, pos, alpha=0.5, edges=G_sem.edges(), arrowstyle="-", edge_color="#000000", width=weights_sem)
x = np.stack(pos.values())[:,0]
y = np.stack(pos.values())[:,1]
ax.set(xlim=(x.min()-pad,x.max()+pad), ylim=(y.min()-pad, y.max()+pad))
for path, lw in zip(linecollection.get_paths(), linecollection.get_linewidths()):
x = path.vertices[:,0]
y = path.vertices[:,1]
w = lw/4
theta = np.arctan2(y[-1] - y[0], x[-1] - x[0])
# ax.plot(x, y, color="blue", linestyle=":")
ax.plot((x-np.sin(theta)*w), y+np.cos(theta)*w, color="blue", linestyle=":")
ax.plot((x+np.sin(theta)*w), y-np.cos(theta)*w, color="blue", linestyle=":")
经过几次思考实验,我意识到需要计算角度,然后相应地调整垫片:
例如,如果该线完全垂直(在90或-90处),则y坐标不会被移动,但x坐标会被移动。对于角度为0或180的线,则相反。
不过,还是有一点偏差。
我怀疑这很相关: matplotlib-如何用数据单位扩展线条宽度?
我认为linewidth
不能直接转换为数据空间
或者,如果这些线集合可以转换为矩形对象,则也可以。
networkx
,而是使用数据空间中的坐标绘制对象。 - Paul Brodersen