Python: networkx: 如何使节点大小自动扩展以适应标签
Python: networkx: How to make node size auto-expand to fit the label
我正在使用 deap 符号回归示例问题中的这段代码,图表显示正常,但我希望节点展开为圆角矩形以自动适应文本 . (我不想通过反复试验来指定节点大小)。我该怎么做?
# show tree
import matplotlib.pyplot as plt
import networkx
nodes, edges, labels = gp.graph(bests[0])
graph = networkx.Graph()
graph.add_nodes_from(nodes)
graph.add_edges_from(edges)
pos = networkx.graphviz_layout(graph, prog="dot")
plt.figure(figsize=(7,7))
networkx.draw_networkx_nodes(graph, pos, node_size=900, node_color="w")
networkx.draw_networkx_edges(graph, pos)
networkx.draw_networkx_labels(graph, pos, labels)
plt.axis("off")
plt.show()
使用 matplotlib 和 networkx 没有一种简单的方法可以做到这一点(当然有足够的代码是可能的)。
Graphviz 在标签方面做得非常出色,并且很容易从 networkx 编写点格式文件以使用 Graphviz 进行处理。
另请查看 https://github.com/chebee7i/nxpd,它可能正是您所需要的。
参数 node_size 接受标量和向量值。标量使所有节点大小相等,而向量可帮助您在列表中指定要用于每个节点的各个值。如果您的节点 ID 是字符串,那么以下策略非常有效。
只需根据每个节点id的长度将大小参数更改为networkx.draw_networkx_nodes
中的列表。适当地选择the_base_size
。
networkx.draw_networkx_nodes(graph, pos,
node_size=[len(v) * the_base_size for v in graph.nodes()],
node_color="w")
您可以调整它以适应您也可以处理标签的情况。
***但是,我不确定在根据标签大小从列表中选择节点大小时是否会保留一对一的对应关系。分享你的结果。我个人将它用于字符串节点 ID,效果很好。
我最近偶然发现了这个问题。即使在 5 年后,也没有直接的方法可以做到这一点。然而,经过多次试验和错误,我终于找到了明智的解决方法。您可以删除节点并只使用带有背景颜色的标签。
pos = nx.spring_layout(graph) # Get positions of your nodes
nx.draw_networkx_nodes(graph, pos=pos, label=labels, bbox=dict(fc="r"))
这里的labels是以节点为键,节点名为值的字典。
实现此目的的另一种微调方法,尤其是当您想要调整每个标签(如颜色、形状、背景等)的 属性 时,最好的方法是使用 [=12= 自己添加标签].
pos = nx.spring_layout(graph) # Get positions of your nodes
for key in pos:
x, y = pos[key]
plt.text(x,y,key,fc="r", ha="center", va="center")
我喜欢@mathfux 的解决方案,因为它在有向图中正确定位了箭头。但它需要一些调整来解决提到的对应问题(位置和颜色列表按布局顺序,而不是节点顺序);还可以处理列表的从零开始的索引。我还发现尺寸按平方律工作,而不是线性工作。这是一个改进的颜色版本,使用 Kamada Kwai 而不是 Spring 所以布局不会每次都改变。
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([(0,1), (1, 1), (1, 7), (2, 1), (2, 2), (2, 3),
(2, 6), (3, 5), (4, 3), (5, 4), (5, 8),
(5, 9), (6, 4), (7, 2), (7, 6), (8, 7)])
labelList="zero one twotwotwo three four five six seven eighteighteight nine".split(' ')
positions=nx.kamada_kawai_layout(G)
plt.figure(figsize =(9, 9))
nx.draw_networkx(G,
node_color =['C{}'.format(i) for i in positions],
pos=positions,
labels={idx: val for idx, val in enumerate(labelList)},
node_size=[len(labelList[i])**2 * 60 for i in positions]
)
我正在使用 deap 符号回归示例问题中的这段代码,图表显示正常,但我希望节点展开为圆角矩形以自动适应文本 . (我不想通过反复试验来指定节点大小)。我该怎么做?
# show tree
import matplotlib.pyplot as plt
import networkx
nodes, edges, labels = gp.graph(bests[0])
graph = networkx.Graph()
graph.add_nodes_from(nodes)
graph.add_edges_from(edges)
pos = networkx.graphviz_layout(graph, prog="dot")
plt.figure(figsize=(7,7))
networkx.draw_networkx_nodes(graph, pos, node_size=900, node_color="w")
networkx.draw_networkx_edges(graph, pos)
networkx.draw_networkx_labels(graph, pos, labels)
plt.axis("off")
plt.show()
使用 matplotlib 和 networkx 没有一种简单的方法可以做到这一点(当然有足够的代码是可能的)。
Graphviz 在标签方面做得非常出色,并且很容易从 networkx 编写点格式文件以使用 Graphviz 进行处理。
另请查看 https://github.com/chebee7i/nxpd,它可能正是您所需要的。
参数 node_size 接受标量和向量值。标量使所有节点大小相等,而向量可帮助您在列表中指定要用于每个节点的各个值。如果您的节点 ID 是字符串,那么以下策略非常有效。
只需根据每个节点id的长度将大小参数更改为networkx.draw_networkx_nodes
中的列表。适当地选择the_base_size
。
networkx.draw_networkx_nodes(graph, pos,
node_size=[len(v) * the_base_size for v in graph.nodes()],
node_color="w")
您可以调整它以适应您也可以处理标签的情况。
***但是,我不确定在根据标签大小从列表中选择节点大小时是否会保留一对一的对应关系。分享你的结果。我个人将它用于字符串节点 ID,效果很好。
我最近偶然发现了这个问题。即使在 5 年后,也没有直接的方法可以做到这一点。然而,经过多次试验和错误,我终于找到了明智的解决方法。您可以删除节点并只使用带有背景颜色的标签。
pos = nx.spring_layout(graph) # Get positions of your nodes
nx.draw_networkx_nodes(graph, pos=pos, label=labels, bbox=dict(fc="r"))
这里的labels是以节点为键,节点名为值的字典。
实现此目的的另一种微调方法,尤其是当您想要调整每个标签(如颜色、形状、背景等)的 属性 时,最好的方法是使用 [=12= 自己添加标签].
pos = nx.spring_layout(graph) # Get positions of your nodes
for key in pos:
x, y = pos[key]
plt.text(x,y,key,fc="r", ha="center", va="center")
我喜欢@mathfux 的解决方案,因为它在有向图中正确定位了箭头。但它需要一些调整来解决提到的对应问题(位置和颜色列表按布局顺序,而不是节点顺序);还可以处理列表的从零开始的索引。我还发现尺寸按平方律工作,而不是线性工作。这是一个改进的颜色版本,使用 Kamada Kwai 而不是 Spring 所以布局不会每次都改变。
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([(0,1), (1, 1), (1, 7), (2, 1), (2, 2), (2, 3),
(2, 6), (3, 5), (4, 3), (5, 4), (5, 8),
(5, 9), (6, 4), (7, 2), (7, 6), (8, 7)])
labelList="zero one twotwotwo three four five six seven eighteighteight nine".split(' ')
positions=nx.kamada_kawai_layout(G)
plt.figure(figsize =(9, 9))
nx.draw_networkx(G,
node_color =['C{}'.format(i) for i in positions],
pos=positions,
labels={idx: val for idx, val in enumerate(labelList)},
node_size=[len(labelList[i])**2 * 60 for i in positions]
)