Source code for networkx.drawing.nx_pylab

"""
**********
Matplotlib
**********

使用 Matplotlib 绘制网络图。

Examples
--------
>>> G = nx.complete_graph(5)
>>> nx.draw(G)

See Also
--------
 - :doc:`matplotlib <matplotlib:index>` 
 - :func:`matplotlib.pyplot.scatter` 
 - :obj:`matplotlib.patches.FancyArrowPatch` 
"""

import collections
import itertools
from numbers import Number

import networkx as nx
from networkx.drawing.layout import (
    circular_layout,
    kamada_kawai_layout,
    planar_layout,
    random_layout,
    shell_layout,
    spectral_layout,
    spring_layout,
)

__all__ = [
    "draw",
    "draw_networkx",
    "draw_networkx_nodes",
    "draw_networkx_edges",
    "draw_networkx_labels",
    "draw_networkx_edge_labels",
    "draw_circular",
    "draw_kamada_kawai",
    "draw_random",
    "draw_spectral",
    "draw_spring",
    "draw_planar",
    "draw_shell",
]


[docs] def draw(G, pos=None, ax=None, **kwds): """使用 Matplotlib 绘制图 G。 将图绘制为一个简单的表示形式,不包含节点标签或边标签,默认使用 Matplotlib 的整个图形区域且不显示轴标签。更多功能丰富的绘制选项,如标题、轴标签等,请参见 `draw_networkx()` 。 Parameters ---------- G : graph 一个 networkx 图 pos : dictionary, 可选 一个以节点为键、位置为值的字典。如果未指定,将计算弹簧布局位置。 请参见 :py:mod:`networkx.drawing.layout` 中的函数来计算节点位置。 ax : Matplotlib Axes 对象, 可选 在指定的 Matplotlib 轴中绘制图。 kwds : 可选关键字 请参见 `networkx.draw_networkx()` 以了解可选关键字的描述。 Examples -------- >>> G = nx.dodecahedral_graph() >>> nx.draw(G) >>> nx.draw(G, pos=nx.spring_layout(G)) # 使用弹簧布局 See Also -------- draw_networkx draw_networkx_nodes draw_networkx_edges draw_networkx_labels draw_networkx_edge_labels Notes ----- 此函数与 `pylab.draw` 和 `pyplot.draw` 同名,因此在使用 `from networkx import *` 时需注意, 可能会覆盖 `pylab.draw` 函数。 使用 pyplot 时: >>> import matplotlib.pyplot as plt >>> G = nx.dodecahedral_graph() >>> nx.draw(G) # networkx 的 draw() >>> plt.draw() # pyplot 的 draw() 另请参见 NetworkX 绘图示例: https://networkx.org/documentation/latest/auto_examples/index.html """ import matplotlib.pyplot as plt if ax is None: cf = plt.gcf() else: cf = ax.get_figure() cf.set_facecolor("w") if ax is None: if cf.axes: ax = cf.gca() else: ax = cf.add_axes((0, 0, 1, 1)) if "with_labels" not in kwds: kwds["with_labels"] = "labels" in kwds draw_networkx(G, pos=pos, ax=ax, **kwds) ax.set_axis_off() plt.draw_if_interactive() return
[docs] def draw_networkx(G, pos=None, arrows=None, with_labels=True, **kwds): r"""使用 Matplotlib 绘制图 G。 使用 Matplotlib 绘制图,并提供节点位置、标签、标题和许多其他绘图功能的选项。 参见 draw() 以进行简单的无标签或坐标轴的绘图。 Parameters ---------- G : graph 一个 networkx 图 pos : dictionary, 可选 一个以节点为键、位置为值的字典。 如果未指定,将计算弹簧布局位置。 参见 :py:mod:`networkx.drawing.layout` 以获取计算节点位置的函数。 arrows : bool 或 None, 可选 (默认=None) 如果为 `None` ,有向图使用 `~matplotlib.patches.FancyArrowPatch` 绘制箭头,无向图使用 `~matplotlib.collections.LineCollection` 绘制边以提高速度。 如果为 `True` ,使用 FancyArrowPatches 绘制箭头(可弯曲且时尚)。 如果为 `False` ,使用 LineCollection 绘制边(线性且快速)。 对于有向图,如果为 True 则绘制箭头。 注意:箭头将与边颜色相同。 arrowstyle : str (有向图默认='-\|>') 对于有向图,选择箭头的样式。 对于无向图默认为 '-' 参见 `matplotlib.patches.ArrowStyle` 以获取更多选项。 arrowsize : int 或 list (默认=10) 对于有向图,选择箭头头部长度和宽度的尺寸。可以传递一个值列表来为箭头头部长度和宽度指定不同的尺寸。 参见 `matplotlib.patches.FancyArrowPatch` 的属性 `mutation_scale` 以获取更多信息。 with_labels : bool (默认=True) 设置为 True 以在节点上绘制标签。 ax : Matplotlib Axes 对象, 可选 在指定的 Matplotlib 轴上绘制图。 nodelist : list (默认=list(G)) 仅绘制指定的节点 edgelist : list (默认=list(G.edges())) 仅绘制指定的边 node_size : 标量或数组 (默认=300) 节点的大小。如果指定数组,则必须与 nodelist 长度相同。 node_color : 颜色或颜色数组 (默认='#1f78b4') 节点的颜色。可以是单个颜色或与 nodelist 长度相同的颜色序列。颜色可以是字符串或 0-1 之间的浮点数的 rgb(或 rgba)元组。如果指定数值,它们将使用 cmap 和 vmin,vmax 参数映射到颜色。参见 matplotlib.scatter 以获取更多细节。 node_shape : 字符串 (默认='o') 节点的形状。规范与 matplotlib.scatter 标记相同,可以是 'so^>v<dph8' 之一。 alpha : float 或 None (默认=None) 节点和边的透明度 cmap : Matplotlib 颜色映射, 可选 用于映射节点强度的颜色映射 vmin,vmax : float, 可选 节点颜色映射的最小值和最大值 linewidths : 标量或序列 (默认=1.0) 符号边框的线宽 width : float 或 float 数组 (默认=1.0) 边的线宽 edge_color : 颜色或颜色数组 (默认='k') 边的颜色。可以是单个颜色或与 edgelist 长度相同的颜色序列。颜色可以是字符串或 0-1 之间的浮点数的 rgb(或 rgba)元组。如果指定数值,它们将使用 edge_cmap 和 edge_vmin,edge_vmax 参数映射到颜色。 edge_cmap : Matplotlib 颜色映射, 可选 用于映射边强度的颜色映射 edge_vmin,edge_vmax : float, 可选 边颜色映射的最小值和最大值 style : 字符串 (默认=实线) 边的线型,例如:'-', '--', '-.', ':' 或单词如 'solid' 或 'dashed'。 (参见 `matplotlib.patches.FancyArrowPatch` : `linestyle` ) labels : dictionary (默认=None) 节点标签,以节点为键的文本标签字典 font_size : int (节点默认=12,边默认=10) 文本标签的字体大小 font_color : 颜色 (默认='k' 黑色) 字体颜色字符串。颜色可以是字符串或 0-1 之间的浮点数的 rgb(或 rgba)元组。 font_weight : 字符串 (默认='normal') 字体粗细 font_family : 字符串 (默认='sans-serif') 字体系列 label : 字符串, 可选 图例的标签 hide_ticks : bool, 可选 隐藏坐标轴的刻度。当为 `True` (默认)时,刻度和刻度标签将从坐标轴中移除。要设置刻度和刻度标签为 pyplot 默认值,请使用 ``hide_ticks=False`` 。 kwds : 可选关键字 参见 networkx.draw_networkx_nodes(), networkx.draw_networkx_edges(), 和 networkx.draw_networkx_labels() 以获取可选关键字的描述。 Notes ----- 对于有向图,箭头绘制在头部末端。可以通过关键字 arrows=False 关闭箭头。 Examples -------- >>> G = nx.dodecahedral_graph() >>> nx.draw(G) >>> nx.draw(G, pos=nx.spring_layout(G)) # 使用弹簧布局 >>> import matplotlib.pyplot as plt >>> limits = plt.axis("off") # 关闭坐标轴 另请参见 NetworkX 绘图示例: https://networkx.org/documentation/latest/auto_examples/index.html See Also -------- draw draw_networkx_nodes draw_networkx_edges draw_networkx_labels draw_networkx_edge_labels """ from inspect import signature import matplotlib.pyplot as plt # Get all valid keywords by inspecting the signatures of draw_networkx_nodes, # draw_networkx_edges, draw_networkx_labels valid_node_kwds = signature(draw_networkx_nodes).parameters.keys() valid_edge_kwds = signature(draw_networkx_edges).parameters.keys() valid_label_kwds = signature(draw_networkx_labels).parameters.keys() # Create a set with all valid keywords across the three functions and # remove the arguments of this function (draw_networkx) valid_kwds = (valid_node_kwds | valid_edge_kwds | valid_label_kwds) - { "G", "pos", "arrows", "with_labels", } if any(k not in valid_kwds for k in kwds): invalid_args = ", ".join([k for k in kwds if k not in valid_kwds]) raise ValueError(f"Received invalid argument(s): {invalid_args}") node_kwds = {k: v for k, v in kwds.items() if k in valid_node_kwds} edge_kwds = {k: v for k, v in kwds.items() if k in valid_edge_kwds} label_kwds = {k: v for k, v in kwds.items() if k in valid_label_kwds} if pos is None: pos = nx.drawing.spring_layout(G) # default to spring layout draw_networkx_nodes(G, pos, **node_kwds) draw_networkx_edges(G, pos, arrows=arrows, **edge_kwds) if with_labels: draw_networkx_labels(G, pos, **label_kwds) plt.draw_if_interactive()
[docs] def draw_networkx_nodes( G, pos, nodelist=None, node_size=300, node_color="#1f78b4", node_shape="o", alpha=None, cmap=None, vmin=None, vmax=None, ax=None, linewidths=None, edgecolors=None, label=None, margins=None, hide_ticks=True, ): """绘制图 G 的节点。 此函数仅绘制图 G 的节点。 Parameters ---------- G : 图 一个 networkx 图 pos : 字典 一个以节点为键、位置为值的字典。 位置应为长度为 2 的序列。 ax : Matplotlib Axes 对象, 可选 在指定的 Matplotlib 轴上绘制图。 nodelist : 列表 (默认 list(G)) 仅绘制指定的节点 node_size : 标量或数组 (默认=300) 节点的大小。如果是一个数组,必须与 nodelist 长度相同。 node_color : 颜色或颜色数组 (默认='#1f78b4') 节点的颜色。可以是单一颜色或与 nodelist 长度相同的颜色序列。颜色可以是字符串或 0-1 之间的浮点数组成的 rgb(或 rgba)元组。如果指定数值,它们将使用 cmap 和 vmin,vmax 参数映射为颜色。详见 matplotlib.scatter。 node_shape : 字符串 (默认='o') 节点的形状。规范与 matplotlib.scatter 标记相同,可以是 'so^>v<dph8' 之一。 alpha : 浮点数或浮点数数组 (默认=None) 节点的透明度。可以是一个单一的 alpha 值,应用于所有节点颜色;或者是一个数组,数组元素按顺序应用于颜色(必要时循环应用 alpha 多次)。 cmap : Matplotlib 颜色映射 (默认=None) 用于映射节点强度的颜色映射 vmin,vmax : 浮点数或 None (默认=None) 节点颜色映射的最小值和最大值 linewidths : [None | 标量 | 序列] (默认=1.0) 符号边界的线宽 edgecolors : [None | 标量 | 序列] (默认 = node_color) 节点边界的颜色。可以是单一颜色或与 nodelist 长度相同的颜色序列。颜色可以是字符串或 0-1 之间的浮点数组成的 rgb(或 rgba)元组。如果指定数值,它们将使用 cmap 和 vmin,vmax 参数映射为颜色。详见 `~matplotlib.pyplot.scatter` 。 label : [None | 字符串] 图例标签 margins : 浮点数或 2-元组, 可选 设置轴自动缩放的填充。增加边距以防止节点靠近图像边缘时被裁剪。值应在 ``[0, 1]`` 范围内。详见 :meth:`matplotlib.axes.Axes.margins` 。默认是 `None` ,使用 Matplotlib 默认值。 hide_ticks : bool, 可选 隐藏轴的刻度。当 `True` (默认)时,刻度和刻度标签从轴上移除。要设置刻度和刻度标签为 pyplot 默认值,使用 ``hide_ticks=False`` 。 Returns ------- matplotlib.collections.PathCollection 节点的 `PathCollection` 。 Examples -------- >>> G = nx.dodecahedral_graph() >>> nodes = nx.draw_networkx_nodes(G, pos=nx.spring_layout(G)) 另请参见 NetworkX 绘图示例: https://networkx.org/documentation/latest/auto_examples/index.html See Also -------- draw draw_networkx draw_networkx_edges draw_networkx_labels draw_networkx_edge_labels """ from collections.abc import Iterable import matplotlib as mpl import matplotlib.collections # call as mpl.collections import matplotlib.pyplot as plt import numpy as np if ax is None: ax = plt.gca() if nodelist is None: nodelist = list(G) if len(nodelist) == 0: # empty nodelist, no drawing return mpl.collections.PathCollection(None) try: xy = np.asarray([pos[v] for v in nodelist]) except KeyError as err: raise nx.NetworkXError(f"Node {err} has no position.") from err if isinstance(alpha, Iterable): node_color = apply_alpha(node_color, alpha, nodelist, cmap, vmin, vmax) alpha = None node_collection = ax.scatter( xy[:, 0], xy[:, 1], s=node_size, c=node_color, marker=node_shape, cmap=cmap, vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths, edgecolors=edgecolors, label=label, ) if hide_ticks: ax.tick_params( axis="both", which="both", bottom=False, left=False, labelbottom=False, labelleft=False, ) if margins is not None: if isinstance(margins, Iterable): ax.margins(*margins) else: ax.margins(margins) node_collection.set_zorder(2) return node_collection
class FancyArrowFactory: """使用 `matplotlib.patches.FancyArrowPatch` 绘制箭头""" class ConnectionStyleFactory: def __init__(self, connectionstyles, selfloop_height, ax=None): import matplotlib as mpl import matplotlib.path # call as mpl.path import numpy as np self.ax = ax self.mpl = mpl self.np = np self.base_connection_styles = [ mpl.patches.ConnectionStyle(cs) for cs in connectionstyles ] self.n = len(self.base_connection_styles) self.selfloop_height = selfloop_height def curved(self, edge_index): return self.base_connection_styles[edge_index % self.n] def self_loop(self, edge_index): def self_loop_connection(posA, posB, *args, **kwargs): if not self.np.all(posA == posB): raise nx.NetworkXError( "`self_loop` connection style method" "is only to be used for self-loops" ) # this is called with _screen space_ values # so convert back to data space data_loc = self.ax.transData.inverted().transform(posA) v_shift = 0.1 * self.selfloop_height h_shift = v_shift * 0.5 # put the top of the loop first so arrow is not hidden by node path = self.np.asarray( [ # 1 [0, v_shift], # 4 4 4 [h_shift, v_shift], [h_shift, 0], [0, 0], # 4 4 4 [-h_shift, 0], [-h_shift, v_shift], [0, v_shift], ] ) # Rotate self loop 90 deg. if more than 1 # This will allow for maximum of 4 visible self loops if edge_index % 4: x, y = path.T for _ in range(edge_index % 4): x, y = y, -x path = self.np.array([x, y]).T return self.mpl.path.Path( self.ax.transData.transform(data_loc + path), [1, 4, 4, 4, 4, 4, 4] ) return self_loop_connection def __init__( self, edge_pos, edgelist, nodelist, edge_indices, node_size, selfloop_height, connectionstyle="arc3", node_shape="o", arrowstyle="-", arrowsize=10, edge_color="k", alpha=None, linewidth=1.0, style="solid", min_source_margin=0, min_target_margin=0, ax=None, ): import matplotlib as mpl import matplotlib.patches # call as mpl.patches import matplotlib.pyplot as plt import numpy as np if isinstance(connectionstyle, str): connectionstyle = [connectionstyle] elif np.iterable(connectionstyle): connectionstyle = list(connectionstyle) else: msg = "ConnectionStyleFactory arg `connectionstyle` must be str or iterable" raise nx.NetworkXError(msg) self.ax = ax self.mpl = mpl self.np = np self.edge_pos = edge_pos self.edgelist = edgelist self.nodelist = nodelist self.node_shape = node_shape self.min_source_margin = min_source_margin self.min_target_margin = min_target_margin self.edge_indices = edge_indices self.node_size = node_size self.connectionstyle_factory = self.ConnectionStyleFactory( connectionstyle, selfloop_height, ax ) self.arrowstyle = arrowstyle self.arrowsize = arrowsize self.arrow_colors = mpl.colors.colorConverter.to_rgba_array(edge_color, alpha) self.linewidth = linewidth self.style = style if isinstance(arrowsize, list) and len(arrowsize) != len(edge_pos): raise ValueError("arrowsize should have the same length as edgelist") def __call__(self, i): (x1, y1), (x2, y2) = self.edge_pos[i] shrink_source = 0 # space from source to tail shrink_target = 0 # space from head to target if self.np.iterable(self.node_size): # many node sizes source, target = self.edgelist[i][:2] source_node_size = self.node_size[self.nodelist.index(source)] target_node_size = self.node_size[self.nodelist.index(target)] shrink_source = self.to_marker_edge(source_node_size, self.node_shape) shrink_target = self.to_marker_edge(target_node_size, self.node_shape) else: shrink_source = self.to_marker_edge(self.node_size, self.node_shape) shrink_target = shrink_source shrink_source = max(shrink_source, self.min_source_margin) shrink_target = max(shrink_target, self.min_target_margin) # scale factor of arrow head if isinstance(self.arrowsize, list): mutation_scale = self.arrowsize[i] else: mutation_scale = self.arrowsize if len(self.arrow_colors) > i: arrow_color = self.arrow_colors[i] elif len(self.arrow_colors) == 1: arrow_color = self.arrow_colors[0] else: # Cycle through colors arrow_color = self.arrow_colors[i % len(self.arrow_colors)] if self.np.iterable(self.linewidth): if len(self.linewidth) > i: linewidth = self.linewidth[i] else: linewidth = self.linewidth[i % len(self.linewidth)] else: linewidth = self.linewidth if ( self.np.iterable(self.style) and not isinstance(self.style, str) and not isinstance(self.style, tuple) ): if len(self.style) > i: linestyle = self.style[i] else: # Cycle through styles linestyle = self.style[i % len(self.style)] else: linestyle = self.style if x1 == x2 and y1 == y2: connectionstyle = self.connectionstyle_factory.self_loop( self.edge_indices[i] ) else: connectionstyle = self.connectionstyle_factory.curved(self.edge_indices[i]) return self.mpl.patches.FancyArrowPatch( (x1, y1), (x2, y2), arrowstyle=self.arrowstyle, shrinkA=shrink_source, shrinkB=shrink_target, mutation_scale=mutation_scale, color=arrow_color, linewidth=linewidth, connectionstyle=connectionstyle, linestyle=linestyle, zorder=1, # arrows go behind nodes ) def to_marker_edge(self, marker_size, marker): if marker in "s^>v<d": # `large` markers need extra space return self.np.sqrt(2 * marker_size) / 2 else: return self.np.sqrt(marker_size) / 2
[docs] def draw_networkx_edges( G, pos, edgelist=None, width=1.0, edge_color="k", style="solid", alpha=None, arrowstyle=None, arrowsize=10, edge_cmap=None, edge_vmin=None, edge_vmax=None, ax=None, arrows=None, label=None, node_size=300, nodelist=None, node_shape="o", connectionstyle="arc3", min_source_margin=0, min_target_margin=0, hide_ticks=True, ): r"""绘制图 G 的边。 此函数仅绘制图 G 的边。 Parameters ---------- G : 图 一个 networkx 图 pos : 字典 一个以节点为键、位置为值的字典。 位置应为长度为 2 的序列。 edgelist : 边元组的集合 (默认=G.edges()) 仅绘制指定的边 width : 浮点数或浮点数数组 (默认=1.0) 边的线宽 edge_color : 颜色或颜色数组 (默认='k') 边的颜色。可以是单一颜色或与 edgelist 长度相同的颜色序列。颜色可以是字符串或 0-1 之间的浮点数 rgb(或 rgba)元组。如果指定了数值,它们将使用 edge_cmap 和 edge_vmin、edge_vmax 参数映射为颜色。 style : 字符串或字符串数组 (默认='solid') 边的线型,例如:'-', '--', '-.', ':' 或单词如 'solid' 或 'dashed'。 可以是单一风格或与边列表长度相同的风格序列。 如果给定的风格少于边数,风格将循环使用。 如果给定的风格多于边数,风格将按顺序使用且不会耗尽。 此外,可以使用 `(offset, onoffseq)` 元组作为风格,而不是字符串。 (参见 `matplotlib.patches.FancyArrowPatch` : `linestyle` ) alpha : 浮点数或浮点数数组 (默认=None) 边的透明度。这可以是一个单一的 alpha 值, 在这种情况下,它将应用于所有指定的边。否则,如果它是一个数组,alpha 的元素将按顺序应用于颜色(如果需要,可以多次循环 alpha)。 edge_cmap : Matplotlib 颜色映射, 可选 用于映射边强度的颜色映射 edge_vmin, edge_vmax : 浮点数, 可选 边颜色映射的最小值和最大值 ax : Matplotlib Axes 对象, 可选 在指定的 Matplotlib 轴上绘制图 arrows : 布尔值或 None, 可选 (默认=None) 如果为 `None` ,有向图使用 `~matplotlib.patches.FancyArrowPatch` 绘制箭头,无向图使用 `~matplotlib.collections.LineCollection` 绘制边以提高速度。 如果为 `True` ,使用 FancyArrowPatches 绘制箭头(可弯曲且样式美观)。 如果为 `False` ,使用 LineCollection 绘制边(线性且快速)。 注意:箭头将与边颜色相同。 arrowstyle : 字符串 (默认='-\|>' 用于有向图) 对于有向图和 `arrows==True` 默认值为 '-\|>', 对于无向图默认值为 '-'。 参见 `matplotlib.patches.ArrowStyle` 了解更多选项。 arrowsize : 整数 (默认=10) 对于有向图,选择箭头头部的长度和宽度。参见 `matplotlib.patches.FancyArrowPatch` 的属性 `mutation_scale` 了解更多信息。 connectionstyle : 字符串或字符串可迭代 (默认="arc3") 传递 connectionstyle 参数以创建弯曲的圆弧和圆角半径 rad。例如,connectionstyle='arc3,rad=0.2'。 参见 `matplotlib.patches.ConnectionStyle` 和 `matplotlib.patches.FancyArrowPatch` 了解更多信息。 如果为可迭代对象,索引表示 MultiGraph 的第 i 条边键 node_size : 标量或数组 (默认=300) 节点的大小。尽管此函数不绘制节点,但节点大小用于确定边的位置。 nodelist : 列表, 可选 (默认=G.nodes()) 这提供了 `node_size` 数组的节点顺序(如果它是数组)。 node_shape : 字符串 (默认='o') 用于节点的标记,用于确定边的位置。 规范为 `matplotlib.markers` 标记,例如 'so^>v<dph8' 之一。 label : None 或字符串 图例标签 min_source_margin : 整数 (默认=0) 边在源头的起始处的最小边距(间隙)。 min_target_margin : 整数 (默认=0) 边在目标的末端处的最小边距(间隙)。 hide_ticks : 布尔值, 可选 隐藏轴的刻度。当为 `True` (默认)时,刻度和刻度标签从轴上移除。要将刻度和刻度标签设置为 pyplot 默认值,请使用 ``hide_ticks=False`` 。 Returns ------- matplotlib.collections.LineCollection 或 matplotlib.patches.FancyArrowPatch 列表 如果 ``arrows=True`` ,返回 FancyArrowPatch 列表。 如果 ``arrows=False`` ,返回 LineCollection。 如果 ``arrows=None`` (默认),如果 `G` 是无向图,返回 LineCollection,否则返回 FancyArrowPatch 列表。 Notes ----- 对于有向图,箭头绘制在头部末端。箭头可以通过关键字 arrows=False 或传递没有箭头的 arrowstyle 来关闭。 确保包含 `node_size` 作为关键字参数;箭头是根据节点大小绘制的。 自环始终使用 `~matplotlib.patches.FancyArrowPatch` 绘制,无论 `arrows` 的值或 `G` 是否为有向图。当 ``arrows=False`` 或 ``arrows=None`` 且 `G` 为无向图时,对应于自环的 FancyArrowPatches 不会显式返回。它们应通过 ``Axes.patches`` 属性访问(参见示例)。 Examples -------- >>> G = nx.dodecahedral_graph() >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) >>> G = nx.DiGraph() >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)]) >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) >>> alphas = [0.3, 0.4, 0.5] >>> for i, arc in enumerate(arcs): # 更改弧的 alpha 值 ... arc.set_alpha(alphas[i]) 对应于自环的 FancyArrowPatches 并不总是返回,但始终可以通过 `matplotlib.Axes` 对象的 ``patches`` 属性访问。 >>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() >>> G = nx.Graph([(0, 1), (0, 0)]) # 节点 0 的自环 >>> edge_collection = nx.draw_networkx_edges(G, pos=nx.circular_layout(G), ax=ax) >>> self_loop_fap = ax.patches[0] 另请参见 NetworkX 绘图示例: https://networkx.org/documentation/latest/auto_examples/index.html See Also -------- draw draw_networkx draw_networkx_nodes draw_networkx_labels draw_networkx_edge_labels """ import warnings import matplotlib as mpl import matplotlib.collections # call as mpl.collections import matplotlib.colors # call as mpl.colors import matplotlib.pyplot as plt import numpy as np # The default behavior is to use LineCollection to draw edges for # undirected graphs (for performance reasons) and use FancyArrowPatches # for directed graphs. # The `arrows` keyword can be used to override the default behavior if arrows is None: use_linecollection = not (G.is_directed() or G.is_multigraph()) else: if not isinstance(arrows, bool): raise TypeError("Argument `arrows` must be of type bool or None") use_linecollection = not arrows if isinstance(connectionstyle, str): connectionstyle = [connectionstyle] elif np.iterable(connectionstyle): connectionstyle = list(connectionstyle) else: msg = "draw_networkx_edges arg `connectionstyle` must be str or iterable" raise nx.NetworkXError(msg) # Some kwargs only apply to FancyArrowPatches. Warn users when they use # non-default values for these kwargs when LineCollection is being used # instead of silently ignoring the specified option if use_linecollection: msg = ( "\n\nThe {0} keyword argument is not applicable when drawing edges\n" "with LineCollection.\n\n" "To make this warning go away, either specify `arrows=True` to\n" "force FancyArrowPatches or use the default values.\n" "Note that using FancyArrowPatches may be slow for large graphs.\n" ) if arrowstyle is not None: warnings.warn(msg.format("arrowstyle"), category=UserWarning, stacklevel=2) if arrowsize != 10: warnings.warn(msg.format("arrowsize"), category=UserWarning, stacklevel=2) if min_source_margin != 0: warnings.warn( msg.format("min_source_margin"), category=UserWarning, stacklevel=2 ) if min_target_margin != 0: warnings.warn( msg.format("min_target_margin"), category=UserWarning, stacklevel=2 ) if any(cs != "arc3" for cs in connectionstyle): warnings.warn( msg.format("connectionstyle"), category=UserWarning, stacklevel=2 ) # NOTE: Arrowstyle modification must occur after the warnings section if arrowstyle is None: arrowstyle = "-|>" if G.is_directed() else "-" if ax is None: ax = plt.gca() if edgelist is None: edgelist = list(G.edges) # (u, v, k) for multigraph (u, v) otherwise if len(edgelist): if G.is_multigraph(): key_count = collections.defaultdict(lambda: itertools.count(0)) edge_indices = [next(key_count[tuple(e[:2])]) for e in edgelist] else: edge_indices = [0] * len(edgelist) else: # no edges! return [] if nodelist is None: nodelist = list(G.nodes()) # FancyArrowPatch handles color=None different from LineCollection if edge_color is None: edge_color = "k" # set edge positions edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist]) # Check if edge_color is an array of floats and map to edge_cmap. # This is the only case handled differently from matplotlib if ( np.iterable(edge_color) and (len(edge_color) == len(edge_pos)) and np.all([isinstance(c, Number) for c in edge_color]) ): if edge_cmap is not None: assert isinstance(edge_cmap, mpl.colors.Colormap) else: edge_cmap = plt.get_cmap() if edge_vmin is None: edge_vmin = min(edge_color) if edge_vmax is None: edge_vmax = max(edge_color) color_normal = mpl.colors.Normalize(vmin=edge_vmin, vmax=edge_vmax) edge_color = [edge_cmap(color_normal(e)) for e in edge_color] # compute initial view minx = np.amin(np.ravel(edge_pos[:, :, 0])) maxx = np.amax(np.ravel(edge_pos[:, :, 0])) miny = np.amin(np.ravel(edge_pos[:, :, 1])) maxy = np.amax(np.ravel(edge_pos[:, :, 1])) w = maxx - minx h = maxy - miny # Self-loops are scaled by view extent, except in cases the extent # is 0, e.g. for a single node. In this case, fall back to scaling # by the maximum node size selfloop_height = h if h != 0 else 0.005 * np.array(node_size).max() fancy_arrow_factory = FancyArrowFactory( edge_pos, edgelist, nodelist, edge_indices, node_size, selfloop_height, connectionstyle, node_shape, arrowstyle, arrowsize, edge_color, alpha, width, style, min_source_margin, min_target_margin, ax=ax, ) # Draw the edges if use_linecollection: edge_collection = mpl.collections.LineCollection( edge_pos, colors=edge_color, linewidths=width, antialiaseds=(1,), linestyle=style, alpha=alpha, ) edge_collection.set_cmap(edge_cmap) edge_collection.set_clim(edge_vmin, edge_vmax) edge_collection.set_zorder(1) # edges go behind nodes edge_collection.set_label(label) ax.add_collection(edge_collection) edge_viz_obj = edge_collection # Make sure selfloop edges are also drawn # --------------------------------------- selfloops_to_draw = [loop for loop in nx.selfloop_edges(G) if loop in edgelist] if selfloops_to_draw: edgelist_tuple = list(map(tuple, edgelist)) arrow_collection = [] for loop in selfloops_to_draw: i = edgelist_tuple.index(loop) arrow = fancy_arrow_factory(i) arrow_collection.append(arrow) ax.add_patch(arrow) else: edge_viz_obj = [] for i in range(len(edgelist)): arrow = fancy_arrow_factory(i) ax.add_patch(arrow) edge_viz_obj.append(arrow) # update view after drawing padx, pady = 0.05 * w, 0.05 * h corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady) ax.update_datalim(corners) ax.autoscale_view() if hide_ticks: ax.tick_params( axis="both", which="both", bottom=False, left=False, labelbottom=False, labelleft=False, ) return edge_viz_obj
[docs] def draw_networkx_labels( G, pos, labels=None, font_size=12, font_color="k", font_family="sans-serif", font_weight="normal", alpha=None, bbox=None, horizontalalignment="center", verticalalignment="center", ax=None, clip_on=True, hide_ticks=True, ): """在图 G 上绘制节点标签。 Parameters ---------- G : 图 一个 networkx 图 pos : 字典 一个以节点为键、位置为值的字典。 位置应该是长度为 2 的序列。 labels : 字典 (默认={n: n for n in G}) 节点标签的字典,以节点为键。 labels 中的节点键应出现在 `pos` 中。 如果需要,使用: `{n:lab for n,lab in labels.items() if n in pos}` font_size : 整数 (默认=12) 文本标签的字体大小 font_color : 颜色 (默认='k' 黑色) 字体颜色字符串。颜色可以是字符串或浮点数从 0-1 的 rgb(或 rgba)元组。 font_weight : 字符串 (默认='normal') 字体粗细 font_family : 字符串 (默认='sans-serif') 字体系列 alpha : 浮点数或 None (默认=None) 文本透明度 bbox : Matplotlib bbox, (默认是 Matplotlib 的 ax.text 默认值) 指定节点标签的文本框属性(例如形状、颜色等)。 horizontalalignment : 字符串 (默认='center') 水平对齐方式 {'center', 'right', 'left'} verticalalignment : 字符串 (默认='center') 垂直对齐方式 {'center', 'top', 'bottom', 'baseline', 'center_baseline'} ax : Matplotlib Axes 对象, 可选 在指定的 Matplotlib 轴上绘制图。 clip_on : 布尔值 (默认=True) 在轴边界处裁剪节点标签 hide_ticks : 布尔值, 可选 隐藏轴的刻度。当 `True` (默认)时,刻度和刻度标签从轴上移除。 要设置刻度和刻度标签为 pyplot 默认值,使用 ``hide_ticks=False`` 。 Returns ------- 字典 以节点为键的标签字典 Examples -------- >>> G = nx.dodecahedral_graph() >>> labels = nx.draw_networkx_labels(G, pos=nx.spring_layout(G)) 另请参阅 NetworkX 绘图示例: https://networkx.org/documentation/latest/auto_examples/index.html See Also -------- draw draw_networkx draw_networkx_nodes draw_networkx_edges draw_networkx_edge_labels """ import matplotlib.pyplot as plt if ax is None: ax = plt.gca() if labels is None: labels = {n: n for n in G.nodes()} text_items = {} # there is no text collection so we'll fake one for n, label in labels.items(): (x, y) = pos[n] if not isinstance(label, str): label = str(label) # this makes "1" and 1 labeled the same t = ax.text( x, y, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, transform=ax.transData, bbox=bbox, clip_on=clip_on, ) text_items[n] = t if hide_ticks: ax.tick_params( axis="both", which="both", bottom=False, left=False, labelbottom=False, labelleft=False, ) return text_items
[docs] def draw_networkx_edge_labels( G, pos, edge_labels=None, label_pos=0.5, font_size=10, font_color="k", font_family="sans-serif", font_weight="normal", alpha=None, bbox=None, horizontalalignment="center", verticalalignment="center", ax=None, rotate=True, clip_on=True, node_size=300, nodelist=None, connectionstyle="arc3", hide_ticks=True, ): """绘制边标签。 Parameters ---------- G : 图 一个 networkx 图 pos : 字典 一个以节点为键、位置为值的字典。 位置应该是长度为 2 的序列。 edge_labels : 字典 (默认=None) 边标签的字典,以边的两个节点元组为键。 仅绘制字典中键对应的标签。 label_pos : 浮点数 (默认=0.5) 边标签在边上的位置(0=头部,0.5=中心,1=尾部) font_size : 整数 (默认=10) 文本标签的字体大小 font_color : 颜色 (默认='k' 黑色) 字体颜色字符串。颜色可以是字符串或浮点数从 0-1 的 rgb(或 rgba)元组。 font_weight : 字符串 (默认='normal') 字体粗细 font_family : 字符串 (默认='sans-serif') 字体系列 alpha : 浮点数或 None (默认=None) 文本透明度 bbox : Matplotlib bbox, 可选 指定边标签文本框的属性(例如形状、颜色等)。 默认是 {boxstyle='round', ec=(1.0, 1.0, 1.0), fc=(1.0, 1.0, 1.0)}。 horizontalalignment : 字符串 (默认='center') 水平对齐方式 {'center', 'right', 'left'} verticalalignment : 字符串 (默认='center') 垂直对齐方式 {'center', 'top', 'bottom', 'baseline', 'center_baseline'} ax : Matplotlib Axes 对象, 可选 在指定的 Matplotlib 轴上绘制图。 rotate : 布尔值 (默认=True) 旋转边标签以使其与边平行 clip_on : 布尔值 (默认=True) 在轴边界处裁剪边标签 node_size : 标量或数组 (默认=300) 节点的大小。如果是一个数组,必须与 nodelist 的长度相同。 nodelist : 列表, 可选 (默认=G.nodes()) 这为 `node_size` 数组(如果它是数组)提供节点顺序。 connectionstyle : 字符串或可迭代字符串 (默认="arc3") 传递 connectionstyle 参数以创建具有指定半径的弯曲弧。例如,connectionstyle='arc3,rad=0.2'。 更多信息请参见 `matplotlib.patches.ConnectionStyle` 和 `matplotlib.patches.FancyArrowPatch` 。 如果是可迭代对象,索引表示 MultiGraph 的第 i 条边键。 hide_ticks : 布尔值, 可选 隐藏轴的刻度。当 `True` (默认)时,刻度和刻度标签从轴上移除。 要设置刻度和刻度标签为 pyplot 默认值,请使用 ``hide_ticks=False`` 。 Returns ------- 字典 `字典` 以边为键的标签 Examples -------- >>> G = nx.dodecahedral_graph() >>> edge_labels = nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G)) 另请参阅 NetworkX 绘图示例: https://networkx.org/documentation/latest/auto_examples/index.html See Also -------- draw draw_networkx draw_networkx_nodes draw_networkx_edges draw_networkx_labels """ import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np class CurvedArrowText(mpl.text.Text): def __init__( self, arrow, *args, label_pos=0.5, labels_horizontal=False, ax=None, **kwargs, ): # Bind to FancyArrowPatch self.arrow = arrow # how far along the text should be on the curve, # 0 is at start, 1 is at end etc. self.label_pos = label_pos self.labels_horizontal = labels_horizontal if ax is None: ax = plt.gca() self.ax = ax self.x, self.y, self.angle = self._update_text_pos_angle(arrow) # Create text object super().__init__(self.x, self.y, *args, rotation=self.angle, **kwargs) # Bind to axis self.ax.add_artist(self) def _get_arrow_path_disp(self, arrow): """这是FancyArrowPatch._get_path_in_displaycoord方法的一部分 它省略了方法的第二部分,即路径根据宽度转换为多边形的过程 变换是从ax获取的,而不是从对象获取的,因为对象尚未添加,并且没有变换 """ dpi_cor = arrow._dpi_cor # trans_data = arrow.get_transform() trans_data = self.ax.transData if arrow._posA_posB is not None: posA = arrow._convert_xy_units(arrow._posA_posB[0]) posB = arrow._convert_xy_units(arrow._posA_posB[1]) (posA, posB) = trans_data.transform((posA, posB)) _path = arrow.get_connectionstyle()( posA, posB, patchA=arrow.patchA, patchB=arrow.patchB, shrinkA=arrow.shrinkA * dpi_cor, shrinkB=arrow.shrinkB * dpi_cor, ) else: _path = trans_data.transform_path(arrow._path_original) # Return is in display coordinates return _path def _update_text_pos_angle(self, arrow): # Fractional label position path_disp = self._get_arrow_path_disp(arrow) (x1, y1), (cx, cy), (x2, y2) = path_disp.vertices # Text position at a proportion t along the line in display coords # default is 0.5 so text appears at the halfway point t = self.label_pos tt = 1 - t x = tt**2 * x1 + 2 * t * tt * cx + t**2 * x2 y = tt**2 * y1 + 2 * t * tt * cy + t**2 * y2 if self.labels_horizontal: # Horizontal text labels angle = 0 else: # Labels parallel to curve change_x = 2 * tt * (cx - x1) + 2 * t * (x2 - cx) change_y = 2 * tt * (cy - y1) + 2 * t * (y2 - cy) angle = (np.arctan2(change_y, change_x) / (2 * np.pi)) * 360 # Text is "right way up" if angle > 90: angle -= 180 if angle < -90: angle += 180 (x, y) = self.ax.transData.inverted().transform((x, y)) return x, y, angle def draw(self, renderer): # recalculate the text position and angle self.x, self.y, self.angle = self._update_text_pos_angle(self.arrow) self.set_position((self.x, self.y)) self.set_rotation(self.angle) # redraw text super().draw(renderer) # use default box of white with white border if bbox is None: bbox = {"boxstyle": "round", "ec": (1.0, 1.0, 1.0), "fc": (1.0, 1.0, 1.0)} if isinstance(connectionstyle, str): connectionstyle = [connectionstyle] elif np.iterable(connectionstyle): connectionstyle = list(connectionstyle) else: raise nx.NetworkXError( "draw_networkx_edges arg `connectionstyle` must be" "string or iterable of strings" ) if ax is None: ax = plt.gca() if edge_labels is None: kwds = {"keys": True} if G.is_multigraph() else {} edge_labels = {tuple(edge): d for *edge, d in G.edges(data=True, **kwds)} # NOTHING TO PLOT if not edge_labels: return {} edgelist, labels = zip(*edge_labels.items()) if nodelist is None: nodelist = list(G.nodes()) # set edge positions edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist]) if G.is_multigraph(): key_count = collections.defaultdict(lambda: itertools.count(0)) edge_indices = [next(key_count[tuple(e[:2])]) for e in edgelist] else: edge_indices = [0] * len(edgelist) # Used to determine self loop mid-point # Note, that this will not be accurate, # if not drawing edge_labels for all edges drawn h = 0 if edge_labels: miny = np.amin(np.ravel(edge_pos[:, :, 1])) maxy = np.amax(np.ravel(edge_pos[:, :, 1])) h = maxy - miny selfloop_height = h if h != 0 else 0.005 * np.array(node_size).max() fancy_arrow_factory = FancyArrowFactory( edge_pos, edgelist, nodelist, edge_indices, node_size, selfloop_height, connectionstyle, ax=ax, ) text_items = {} for i, (edge, label) in enumerate(zip(edgelist, labels)): if not isinstance(label, str): label = str(label) # this makes "1" and 1 labeled the same n1, n2 = edge[:2] arrow = fancy_arrow_factory(i) if n1 == n2: connectionstyle_obj = arrow.get_connectionstyle() posA = ax.transData.transform(pos[n1]) path_disp = connectionstyle_obj(posA, posA) path_data = ax.transData.inverted().transform_path(path_disp) x, y = path_data.vertices[0] text_items[edge] = ax.text( x, y, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, rotation=0, transform=ax.transData, bbox=bbox, zorder=1, clip_on=clip_on, ) else: text_items[edge] = CurvedArrowText( arrow, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, transform=ax.transData, bbox=bbox, zorder=1, clip_on=clip_on, label_pos=label_pos, labels_horizontal=not rotate, ax=ax, ) if hide_ticks: ax.tick_params( axis="both", which="both", bottom=False, left=False, labelbottom=False, labelleft=False, ) return text_items
[docs] def draw_circular(G, **kwargs): """绘制图 `G` 并使用圆形布局。 这是一个便捷函数,等效于:: nx.draw(G, pos=nx.circular_layout(G), **kwargs) Parameters ---------- G : 图 一个 networkx 图 kwargs : 可选关键字参数 参见 `draw_networkx` 以了解可选关键字参数的描述。 Notes ----- 每次调用此函数时都会计算布局。对于重复绘图,直接调用 `~networkx.drawing.layout.circular_layout` 并重用结果会更加高效:: >>> G = nx.complete_graph(5) >>> pos = nx.circular_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.path_graph(5) >>> nx.draw_circular(G) See Also -------- :func:`~networkx.drawing.layout.circular_layout` """ draw(G, circular_layout(G), **kwargs)
[docs] def draw_kamada_kawai(G, **kwargs): """绘制图 `G` 使用 Kamada-Kawai 力导向布局。 这是一个便捷函数,等同于:: nx.draw(G, pos=nx.kamada_kawai_layout(G), **kwargs) Parameters ---------- G : graph 一个 networkx 图 kwargs : 可选关键字参数 参见 `draw_networkx` 以了解可选关键字参数的描述。 Notes ----- 每次调用此函数时都会计算布局。 对于重复绘图,直接调用 `~networkx.drawing.layout.kamada_kawai_layout` 并重用结果更为高效:: >>> G = nx.complete_graph(5) >>> pos = nx.kamada_kawai_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.path_graph(5) >>> nx.draw_kamada_kawai(G) See Also -------- :func:`~networkx.drawing.layout.kamada_kawai_layout` """ draw(G, kamada_kawai_layout(G), **kwargs)
[docs] def draw_random(G, **kwargs): """绘制图 `G` 并使用随机布局。 这是一个便捷函数,等效于:: nx.draw(G, pos=nx.random_layout(G), **kwargs) Parameters ---------- G : 图 一个 networkx 图 kwargs : 可选关键字参数 关于可选关键字参数的描述,请参见 `draw_networkx` 。 Notes ----- 每次调用此函数时都会计算布局。 对于重复绘图,直接调用 `~networkx.drawing.layout.random_layout` 并重用结果更为高效:: >>> G = nx.complete_graph(5) >>> pos = nx.random_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.lollipop_graph(4, 3) >>> nx.draw_random(G) See Also -------- :func:`~networkx.drawing.layout.random_layout` """ draw(G, random_layout(G), **kwargs)
[docs] def draw_spectral(G, **kwargs): """绘制图 `G` 使用谱二维布局。 这是一个便捷函数,等价于:: nx.draw(G, pos=nx.spectral_layout(G), **kwargs) 关于节点位置如何确定的更多信息,请参阅 `~networkx.drawing.layout.spectral_layout` 。 Parameters ---------- G : 图 一个 networkx 图 kwargs : 可选关键字 关于可选关键字的描述,请参阅 `draw_networkx` 。 Notes ----- 每次调用此函数时都会计算布局。 对于重复绘图,直接调用 `~networkx.drawing.layout.spectral_layout` 并重用结果更为高效:: >>> G = nx.complete_graph(5) >>> pos = nx.spectral_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.path_graph(5) >>> nx.draw_spectral(G) See Also -------- :func:`~networkx.drawing.layout.spectral_layout` """ draw(G, spectral_layout(G), **kwargs)
[docs] def draw_spring(G, **kwargs): """绘制图 `G` 使用弹簧布局。 这是一个便捷函数,等同于:: nx.draw(G, pos=nx.spring_layout(G), **kwargs) Parameters ---------- G : 图 一个 networkx 图 kwargs : 可选关键字参数 参见 `draw_networkx` 以了解可选关键字参数的描述。 Notes ----- `~networkx.drawing.layout.spring_layout` 也是 `draw` 的默认布局,因此此函数等同于 `draw` 。 每次调用此函数时都会计算布局。对于重复绘图,直接调用 `~networkx.drawing.layout.spring_layout` 并重用结果更为高效:: >>> G = nx.complete_graph(5) >>> pos = nx.spring_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.path_graph(20) >>> nx.draw_spring(G) See Also -------- draw :func:`~networkx.drawing.layout.spring_layout` """ draw(G, spring_layout(G), **kwargs)
[docs] def draw_shell(G, nlist=None, **kwargs): """绘制带有壳布局的 networkx 图 `G` 。 这是一个便捷函数,等效于:: nx.draw(G, pos=nx.shell_layout(G, nlist=nlist), **kwargs) Parameters ---------- G : 图 一个 networkx 图 nlist : 节点列表的列表,可选 包含表示壳的节点列表的列表。 默认值为 `None` ,表示所有节点都在一个壳中。 详情请参见 `~networkx.drawing.layout.shell_layout` 。 kwargs : 可选关键字 有关可选关键字的描述,请参见 `draw_networkx` 。 Notes ----- 每次调用此函数时都会计算布局。 对于重复绘图,直接调用 `~networkx.drawing.layout.shell_layout` 并重用结果更为高效:: >>> G = nx.complete_graph(5) >>> pos = nx.shell_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.path_graph(4) >>> shells = [[0], [1, 2, 3]] >>> nx.draw_shell(G, nlist=shells) See Also -------- :func:`~networkx.drawing.layout.shell_layout` """ draw(G, shell_layout(G, nlist=nlist), **kwargs)
[docs] def draw_planar(G, **kwargs): """绘制具有平面布局的平面网络x图 `G` 。 这是一个便捷函数,等效于:: nx.draw(G, pos=nx.planar_layout(G), **kwargs) Parameters ---------- G : 图 一个平面网络x图 kwargs : 可选关键字 参见 `draw_networkx` 以了解可选关键字的描述。 Raises ------ NetworkXException 当 `G` 不是平面图时 Notes ----- 每次调用此函数时都会计算布局。 对于重复绘图,直接调用 `~networkx.drawing.layout.planar_layout` 并重用结果更为高效:: >>> G = nx.path_graph(5) >>> pos = nx.planar_layout(G) >>> nx.draw(G, pos=pos) # 绘制原始图 >>> # 绘制子图,重用相同的节点位置 >>> nx.draw(G.subgraph([0, 1, 2]), pos=pos, node_color="red") Examples -------- >>> G = nx.path_graph(4) >>> nx.draw_planar(G) See Also -------- :func:`~networkx.drawing.layout.planar_layout` """ draw(G, planar_layout(G), **kwargs)
def apply_alpha(colors, alpha, elem_list, cmap=None, vmin=None, vmax=None): """应用一个alpha值(或alpha值列表)到提供的颜色上。 Parameters ---------- colors : 颜色字符串或浮点数数组(默认='r') 元素的颜色。可以是单个颜色格式字符串, 或与nodelist长度相同的颜色序列。 如果指定数值,它们将使用cmap和vmin,vmax参数映射到 颜色。详见matplotlib.scatter。 alpha : 浮点数或浮点数数组 元素的alpha值。这可以是一个单一的alpha值, 在这种情况下,它将应用于所有颜色元素。否则, 如果是一个数组,alpha的元素将按顺序应用于颜色 (如有必要,循环多次)。 elem_list : networkx对象数组 正在着色的元素列表。这些可以是节点、 边或标签。 cmap : matplotlib颜色映射 如果colors是与颜色映射上的点对应的浮点数列表, 则使用的颜色映射。 vmin, vmax : 浮点数 如果使用颜色映射,用于标准化颜色的最小值和最大值 Returns ------- rgba_colors : numpy ndarray 包含每个节点颜色的RGBA格式值的数组。 """ from itertools import cycle, islice import matplotlib as mpl import matplotlib.cm # call as mpl.cm import matplotlib.colors # call as mpl.colors import numpy as np # If we have been provided with a list of numbers as long as elem_list, # apply the color mapping. if len(colors) == len(elem_list) and isinstance(colors[0], Number): mapper = mpl.cm.ScalarMappable(cmap=cmap) mapper.set_clim(vmin, vmax) rgba_colors = mapper.to_rgba(colors) # Otherwise, convert colors to matplotlib's RGB using the colorConverter # object. These are converted to numpy ndarrays to be consistent with the # to_rgba method of ScalarMappable. else: try: rgba_colors = np.array([mpl.colors.colorConverter.to_rgba(colors)]) except ValueError: rgba_colors = np.array( [mpl.colors.colorConverter.to_rgba(color) for color in colors] ) # Set the final column of the rgba_colors to have the relevant alpha values try: # If alpha is longer than the number of colors, resize to the number of # elements. Also, if rgba_colors.size (the number of elements of # rgba_colors) is the same as the number of elements, resize the array, # to avoid it being interpreted as a colormap by scatter() if len(alpha) > len(rgba_colors) or rgba_colors.size == len(elem_list): rgba_colors = np.resize(rgba_colors, (len(elem_list), 4)) rgba_colors[1:, 0] = rgba_colors[0, 0] rgba_colors[1:, 1] = rgba_colors[0, 1] rgba_colors[1:, 2] = rgba_colors[0, 2] rgba_colors[:, 3] = list(islice(cycle(alpha), len(rgba_colors))) except TypeError: rgba_colors[:, -1] = alpha return rgba_colors