我正在使用networkx
中的DiGraph类,文档应该允许自循环。但是,当使用Matplotlib绘图时,我无法看到任何自循环,无论是否
print(G.nodes_with_selfloops())
返回具有自循环的节点列表。 我想知道如何显示这些自循环。
我正在使用这些函数绘制:
nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)
nx.draw_networkx(G,pos,font_color='k',node_size=500, edge_color='b', alpha=0.5)
答案 0 :(得分:0)
https://networkx.github.io/documentation/networkx-1.10/reference/drawing.html
将来,可以删除图形可视化功能 NetworkX或仅作为附加软件包提供。
我们强烈建议人们使用工具可视化他们的图表 致力于这项任务。
上面的链接提供了许多内置可视化的替代方案。请考虑他们提供的替代方案以节省自己很多时间。
我个人使用cytoscape,它接受.graphml
格式的文件。将图表导出到.graphml
非常简单:
nx.write_graphml(graph, path_to_file)
答案 1 :(得分:0)
我在尝试使用 networkx 绘制和弦图时遇到了同样的问题。在旧版本的 networkx (2.5) 上,自循环在节点后面画了一个点(这意味着您根本看不到它们)。在较新的版本 (2.6.2) 上,自循环的绘制方向与下图相同
Self-loops in the networkx 2.6.2
如果这对您来说已经足够了,请尝试更新 networkx。看起来这个问题已经解决了。至少,documentation 有一些关于它的信息
但是,如果这对您来说还不够(就像对我一样),您可以编写一个自定义代码来更好地绘制自循环。我为该任务创建了一个 repository。它允许绘制不同方向的自环,远离中心:
以下是其背后的简单想法:
如果这听起来太复杂,我希望图片能说清楚: Visualization of anchors
代码如下:
from typing import Optional
import matplotlib.pyplot as plt
from matplotlib.path import Path as MplPath # To avoid collisions with pathlib.Path
import matplotlib.patches as patches
import networkx as nx
import numpy as np
# Some useful functions
def normalize_vector(vector: np.array, normalize_to: float) -> np.array:
"""Make `vector` norm equal to `normalize_to`
vector: np.array
Vector with 2 coordinates
normalize_to: float
A norm of the new vector
Returns
-------
Vector with the same direction, but length normalized to `normalize_to`
"""
vector_norm = np.linalg.norm(vector)
return vector * normalize_to / vector_norm
def orthogonal_vector(point: np.array, width: float, normalize_to: Optional[float] = None) -> np.array:
"""Get orthogonal vector to a `point`
point: np.array
Vector with x and y coordinates of a point
width: float
Distance of the x-coordinate of the new vector from the `point` (in orthogonal direction)
normalize_to: Optional[float] = None
If a number is provided, normalize a new vector length to this number
Returns
-------
Array with x and y coordinates of the vector, which is orthogonal to the vector from (0, 0) to `point`
"""
EPSILON = 0.000001
x = width
y = -x * point[0] / (point[1] + EPSILON)
ort_vector = np.array([x, y])
if normalize_to is not None:
ort_vector = normalize_vector(ort_vector, normalize_to)
return ort_vector
def draw_self_loop(
point: np.array,
ax: Optional[plt.Axes] = None,
padding: float = 1.5,
width: float = 0.3,
plot_size: int = 10,
linewidth = 0.2,
color: str = "pink",
alpha: float = 0.5
) -> plt.Axes:
"""Draw a loop from `point` to itself
!Important! By "center" we assume a (0, 0) point. If your data is centered around a different points,
it is strongly recommended to center it around zero. Otherwise, you will probably get ugly plots
Parameters
----------
point: np.array
1D array with 2 coordinates of the point. Loop will be drawn from and to these coordinates.
padding: float = 1.5
Controls how the distance of the loop from the center. If `padding` > 1, the loop will be
from the outside of the `point`. If `padding` < 1, the loop will be closer to the center
width: float = 0.3
Controls the width of the loop
linewidth: float = 0.2
Width of the line of the loop
ax: Optional[matplotlib.pyplot.Axes]:
Axis on which to draw a plot. If None, a new Axis is generated
plot_size: int = 7
Size of the plot sides in inches. Ignored if `ax` is provided
color: str = "pink"
Color of the arrow
alpha: float = 0.5
Opacity of the edge
Returns
-------
Matplotlib axes with the self-loop drawn
"""
if ax is None:
fig, ax = plt.subplots(figsize=(plot_size, plot_size))
point_with_padding = padding * point
ort_vector = orthogonal_vector(point, width, normalize_to=width)
first_anchor = ort_vector + point_with_padding
second_anchor = -ort_vector + point_with_padding
verts = [point, first_anchor, second_anchor, point]
codes = [MplPath.MOVETO, MplPath.CURVE4, MplPath.CURVE4, MplPath.CURVE4]
path = MplPath(verts, codes)
patch = patches.FancyArrowPatch(
path=path,
facecolor='none',
lw=linewidth,
arrowstyle="-|>",
color=color,
alpha=alpha,
mutation_scale=30 # arrowsize in draw_networkx_edges()
)
ax.add_patch(patch)
return ax
绘制绘图的代码示例:
fig, ax = plt.subplots(figsize=(6, 6))
graph = nx.DiGraph(
np.array([
[1, 1, 1, 1, 1],
[1, 0, 1, 0, 0],
[1, 1, 1, 0, 1],
[0, 0, 1, 0, 1],
[1, 1, 1, 1, 1]
])
)
pos = nx.circular_layout(graph, center=(0, 0))
nx.draw_networkx_nodes(graph, pos, ax=ax)
nx.draw_networkx_edges(graph, pos, ax=ax)
for node in graph.nodes:
if (node, node) in graph.edges:
draw_self_loop(point=pos[node], ax=ax, color="k", alpha=1, linewidth=1)
ax.set_xlim(-1.5, 1.5)
ax.set_ylim(-1.5, 1.5)
您可以在我的repository
中找到更多示例和函数来绘制漂亮的和弦图