networkx绘制超500节点图出现Invalid RGBA argument: nan错误如何解决
问题描述
绘制含1000个节点的网络图时触发报错,经排查是颜色映射mapper中存在nan值,该代码在节点数小于500时可正常运行,节点数超过500时就会触发报错。
报错信息
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) ~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_axes.py in _parse_scatter_color_args(c, edgecolors, kwargs, xsize, get_next_color_func) 4290 try: # Is 'c' acceptable as PathCollection facecolors? -> 4291 colors = mcolors.to_rgba_array(c) 4292 except (TypeError, ValueError) as err: ~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/colors.py in to_rgba_array(c, alpha) 340 else: --> 341 return np.array([to_rgba(cc, alpha) for cc in c]) 342 ~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/colors.py in <listcomp>(.0) 340 else: --> 341 return np.array([to_rgba(cc, alpha) for cc in c]) 342 ~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/colors.py in to_rgba(c, alpha) 188 if rgba is None: # Suppress exception chaining of cache lookup failure. --> 189 rgba = _to_rgba_no_colorcycle(c, alpha) 190 try: ~/opt/anaconda3/lib/python3.8/site-packages/matplotlib/colors.py in _to_rgba_no_colorcycle(c, alpha) 262 if not np.iterable(c): --> 263 raise ValueError(f"Invalid RGBA argument: {orig_c!r}") 264 if len(c) not in [3, 4]: ValueError: Invalid RGBA argument: nan
ValueError: 'c' argument must be a color, a sequence of colors, or a sequence of numbers, not dict_values(['#0010ff', '#40ffb7', '#00a4ff', '#40ffb7', '#00a4ff', '#40ffb7', '#ffb900', '#0010ff', nan, '#000080', '#000080', '#000080', '#000080', nan, '#0010ff', '#0010ff', '#800000', '#0010ff', '#0010ff', '#ff3000', '#0010ff', nan, '#00a4ff', '#0010ff', '#0010ff', '#ff3000', nan, nan, '#000080', '#0010ff', '#0010ff', '#0010ff', nan, nan, '#0010ff', nan, nan, '#0010ff', '#0010ff', nan, '#40ffb7', '#00a4ff', '#00a4ff', '#00a4ff', '#0010ff', '#0010ff', '#0010ff', nan, '#800000', nan])
原代码
import networkx as nx import numpy as np import pandas as pd from matplotlib import pyplot as plt, colors as mcolor # Sample DataFrames df1 = pd.DataFrame({ 'Node': ['A', 'A', 'B', 'B', 'B', 'Z'], 'Edge': ['B', 'D', 'N', 'A', 'X', 'C'] }) df2 = pd.DataFrame({ 'Nodes': ['A', 'B', 'C', 'D', 'N', 'S', 'X'], 'Attribute': [-1, 0, -1.5, 1, 1, 9, 0] }) # Simplified construction of `colour_map` uni_val = df2['Attribute'].unique() colors = plt.cm.jet(np.linspace(0, 1, len(uni_val))) # Map colours to_hex then zip with mapper = dict(zip(uni_val, map(mcolor.to_hex, colors))) G = nx.from_pandas_edgelist(df1, source='Node', target='Edge') # Create Colour map. Ensure all nodes have a value via reindex color_map = ( df2.set_index('Nodes')['Attribute'].map(mapper) .reindex(G.nodes(), fill_value='black') ) # Add Attribute to each node nx.set_node_attributes(G, color_map, name="colour") # Then draw with colours based on attribute values: nx.draw(G, node_color=nx.get_node_attributes(G, 'colour').values(), with_labels=True) plt.show()
问题原因
报错的核心是颜色映射过程中产生了nan值,matplotlib无法将nan识别为合法的颜色值。当节点数较少时,Attribute列刚好没有空值、映射全部命中,不会触发报错;节点数增多后,df2的Attribute列出现空值,或者部分属性值无法匹配到mapper中的键,就会生成nan流入后续绘图步骤。
注意原代码中reindex的fill_value='black'仅能补全G中存在但df2中不存在的节点的颜色,无法处理df2中已经存在的节点映射后产生的nan。
解决方案
在映射之后新增一步fillna,提前将所有映射产生的nan替换为默认颜色即可,修改后的核心代码段如下:
color_map = ( df2.set_index('Nodes')['Attribute'].map(mapper) .fillna('black') # 新增:将映射生成的nan替换为黑色 .reindex(G.nodes(), fill_value='black') )
如果需要为属性为空的节点指定其他颜色,替换fillna的参数即可。也可以在构建mapper时显式为nan指定映射颜色:
mapper = dict(zip(uni_val, map(mcolor.to_hex, colors))) mapper[np.nan] = 'black' # 显式为nan指定对应颜色
内容的提问来源于stack exchange,提问作者LdM
相关产品推荐
相关产品推荐

