Skip to content

networkx_draw_nodes fails when both node_color and node_shape are lists #8350

@J08nY

Description

@J08nY

Current Behavior

Currently, the code below throws an exception:

import networkx as nx

g = nx.Graph()
for i in range(5):
    g.add_node(i)

colors = ["red"] * 5
shapes = ["o", "^", "o", "^", "o"]

pos = nx.random_layout(g)
nx.draw_networkx_nodes(g, pos, node_color=colors, node_shape=shapes)

The exception:

Traceback (most recent call last):
  File "tester.py", line 11, in <module>
    nx.draw_networkx_nodes(g, pos, node_color=colors, node_shape=shapes)
  File "networkx/drawing/nx_pylab.py", line 1438, in draw_networkx_nodes
    node_collection = ax.scatter(
                      ^^^^^^^^^^^
  File "matplotlib/_api/deprecation.py", line 453, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "matplotlib/__init__.py", line 1524, in inner
    return func(
           ^^^^^
  File "/matplotlib/axes/_axes.py", line 4954, in scatter
    self._parse_scatter_color_args(
  File "matplotlib/axes/_axes.py", line 4777, in _parse_scatter_color_args
    raise invalid_shape_exception(len(colors), xsize)
ValueError: 'c' argument has 5 elements, which is inconsistent with 'x' and 'y' with size 0.

Expected Behavior

I expected the code to draw a graph of red nodes with varying labels.

Steps to Reproduce

Run the code.

Environment

Python version: 3.12.11
NetworkX version: 3.5

Additional context

I believe the issue is with the code below:

if not isinstance(node_shape, np.ndarray) and not isinstance(node_shape, list):
node_shape = np.array([node_shape for _ in range(len(nodelist))])
for shape in np.unique(node_shape):
node_collection = ax.scatter(
xy[node_shape == shape, 0],
xy[node_shape == shape, 1],
s=node_size,
c=node_color,
marker=shape,
cmap=cmap,
vmin=vmin,
vmax=vmax,
alpha=alpha,
linewidths=linewidths,
edgecolors=edgecolors,
label=label,
)

It looks as if it tries to handle a node_shape value that is an array/list as well as one that is just a string. It does so in a weird way. Essentially breaking the function when node_shape is not a single character (the return value is then different as well). I see that the docstring specifies the node_shape as a single character only, though when I looked at the code it seemed to be trying to handle list values, hence the bug report.

I think handling multiple marker shapes with the current API of the draw_networkx_nodes (returns PathCollection) is not possible, so the code around the node_shape should be dropped and simply passed straight to ax.scatter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    VisualizationRelated to graph visualization or layout

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions