You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NetworkX与Python在mplleaflet绘制有向图时遇ValueError报错

Fixing "ValueError: Unrecognized code: S" When Plotting Directed Graphs with mplleaflet

I ran into this exact issue before—mplleaflet's path parser doesn't handle the special path code S that NetworkX uses to draw arrows for directed graphs. Here's why it happens and how to fix it:

Root Cause

When you draw a directed graph with nx.draw(), NetworkX uses matplotlib's path code S (for smooth quadratic Bézier curves) to render arrowheads. But mplleaflet's underlying utility function (iter_rings in utils.py) only supports basic path codes like M (move), L (line), and Z (close). When it hits S, it throws that ValueError.

Solution 1: Disable Arrows (Quick Fix)

If you just need to visualize the graph structure temporarily, turn off arrows in the NetworkX draw call. This avoids generating the problematic S path codes entirely:

fig, ax = plt.subplots(figsize=(20,13))
# Add arrows=False to skip arrowhead rendering
nx.draw(G, pos=coordinates_dict, arrows=False)
mplleaflet.display(fig=fig)

Solution 2: Manual Arrow Drawing (Preserve Directionality)

If you need to keep the directed arrows, avoid letting NetworkX draw them directly. Instead, draw nodes/edges without arrows, then manually add arrows using matplotlib's arrow() function:

import mplleaflet
import matplotlib.pyplot as plt
import networkx as nx
import numpy as np
import pandas as pd

# ... (your existing code to load data and build graph)

fig, ax = plt.subplots(figsize=(20,13))
# Draw nodes and edges without arrows
nx.draw_networkx_nodes(G, pos=coordinates_dict, ax=ax)
nx.draw_networkx_edges(G, pos=coordinates_dict, arrows=False, ax=ax)

# Manually draw arrows for each directed edge
for u, v in G.edges():
    x1, y1 = coordinates_dict[u]
    x2, y2 = coordinates_dict[v]
    
    # Adjust arrow endpoint to avoid overlapping with nodes
    dx = x2 - x1
    dy = y2 - y1
    edge_length = np.sqrt(dx**2 + dy**2)
    if edge_length > 0:
        # Shorten the arrow slightly so it points at the node's edge
        x2 = x1 + dx * 0.9
        y2 = y1 + dy * 0.9
        ax.arrow(x1, y1, x2 - x1, y2 - y1, 
                 head_width=0.005, head_length=0.005, 
                 fc='black', ec='black')

mplleaflet.display(fig=fig)

Solution 3: Patch mplleaflet's Source Code (Advanced)

If you want to fix mplleaflet itself (not recommended for beginners, since it modifies a third-party library), edit the utils.py file in your mplleaflet installation directory:

  1. Find the iter_rings function (usually in ~/anaconda3/lib/python3.7/site-packages/mplleaflet/utils.py for your setup)
  2. Add a check to ignore the S code:
def iter_rings(data, pathcodes):
    ring = []
    for point, code in zip(data, pathcodes):
        if code in ['M', 'L']:
            ring.append(point)
        elif code == 'Z':
            yield ring
            ring = []
        elif code == 'S':  # Ignore smooth curve code used for arrows
            continue
        else:
            raise ValueError('Unrecognized code: {}'.format(code))
    if len(ring):
        yield ring

⚠️ Note: Modifying library code can break other projects, so use this in a virtual environment or back up the file first.

内容的提问来源于stack exchange,提问作者Jonaash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:39:05