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

Matplotlib饼图仪表盘箭头异常截断问题求助

Matplotlib Gauge Chart Arrow Gets Clipped Between Sectors 2 and 4

I'm building a gauge chart using Matplotlib's pie plots, but I'm running into an issue: when the arrow points between sector 2 and 4, the top part of the arrow gets clipped as if there's an invisible boundary between the left corner of sector 2 and the right corner of sector 4. Arrows in other positions display fine. I initially suspected it was a figsize issue, but I'm not sure. Here's my code:

import matplotlib.pyplot as plt
import math
import numpy as np  # Missing import added here!
from matplotlib.patches import Circle  # Missing import added here!
from textwrap import wrap

theta = 0.2
group_size=[10,10,10,10,10,50]
mid = [18,54,90,126,162]
labels=['1','2','3','4','5','']
labels = [ '\n'.join(wrap(l, 9)) for l in labels ]

fig, ax = plt.subplots()
ax.axis('equal')

# Outer dark pie
pie3 = ax.pie(group_size, radius=2.2, colors=['k'] ,startangle=180,counterclock=False)
# Center white circle
my_circle=plt.Circle( (0,0), 0.4, color='white')
p=plt.gcf()
p.gca().add_artist(my_circle)

# Inner labeled pie
pie4 = ax.pie([10,10,10,10,10,50], radius=2, labeldistance=0.9, labels=labels, startangle=180,rotatelabels =True,counterclock=False)
plt.setp(pie4[1], rotation_mode="anchor", ha="center", va="center")

# Adjust label styling
for tx in pie4[1]:
    font = tx.get_fontsize()
    tx.set_fontsize(12)
    rot = tx.get_rotation()
    tx.set_rotation(rot+90+(1-rot//180)*180)

# Add white edges to pie wedges
for pie_wedge in pie3[0]:
    pie_wedge.set_edgecolor('white')
for pie_wedge in pie4[0]:
    pie_wedge.set_edgecolor('white')
    pie_wedge.set_linewidth(4)

# Arrow base circles
ax.add_patch(Circle((0, 0), radius=0.15, facecolor='k',zorder=12))
ax.add_patch(Circle((0, 0), radius=0.13, facecolor='w',zorder=13))

# First arrow
ax.arrow(0, 0, 1.7 * np.sin(math.radians(theta*180-90)), 1.7 * np.cos(math.radians(theta*180-90)), \
         width=0.15, head_width=0.15, head_length=0.2, fc='k', ec='k')

# Second arrow (the one that gets clipped)
theta2 = 0.45
ax.arrow(0, 0, 1.7 * np.sin(math.radians(theta2*180-90)), 1.7 * np.cos(math.radians(theta2*180-90)), \
         width=0.15, head_width=0.15, head_length=0.2, fc='k', ec='k',zorder=20)

Why This Happens

This isn't actually a figsize issue — it's about the axis limits. When Matplotlib draws the pie charts, it automatically sets the axis limits to fit the pie's radius (2.2 in your outer pie). However, your arrows have a total length of ~1.9 (1.7 shaft + 0.2 head), and when pointing toward the top-right/top-left (between sectors 2 and 4), the arrow's tip pushes beyond the axis's calculated limits, causing it to be clipped.

The reason this only happens between sectors 2 and 4 is that those sectors are aligned with the top half of the chart, where the axis's upper/y-limit is exactly at the outer edge of the pie. Arrows pointing down or to the sides don't exceed the limits because those directions have extra "space" in the axis bounds (or the arrow length doesn't push past the limit in that direction).

Fix

To fix this, you just need to manually expand the axis limits to accommodate the full length of the arrows. Add these lines at the very end of your code:

# Expand axis limits to fit arrows
ax.set_xlim(-2.3, 2.3)
ax.set_ylim(-2.3, 2.3)

You can adjust the values (2.3) slightly if needed — just make sure they're larger than the total length of your arrows plus any padding you want. Alternatively, you can use ax.autoscale() to let Matplotlib automatically adjust the limits, but manual setting is more reliable for gauge charts where you want consistent bounds.

Also, note I added two missing imports (numpy and Circle from matplotlib.patches) in the code above — your original code would throw errors without these, so that's a quick fix too.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:09:22