使用NetworkX与Python在mplleaflet绘制有向图时遇ValueError报错
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:
- Find the
iter_ringsfunction (usually in~/anaconda3/lib/python3.7/site-packages/mplleaflet/utils.pyfor your setup) - Add a check to ignore the
Scode:
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

