Matplotlib极坐标柱状图:实现中心空心环(甜甜圈孔)
Hey there, let's sort out that donut hole for your polar bar chart! The issue with setting bottom=1 directly is that it shifts your bars upward by 1 (making their total height 1 + original value), which isn't what you want. Instead, we need to keep your data values intact while leaving the 0-1 inner region blank. Here are two straightforward solutions:
Solution 1: Adjust Bar Position & Height (Cleanest for Your Data)
Since your data doesn't include values in the 0-1 range, we can anchor the bars at bottom=1 and reduce their height by 1 to keep the top of each bar aligned with your original data values. This way, the 0-1 area stays empty, and your chart's scale remains accurate.
Here's the modified code with key changes highlighted (plus a small cleanup for redundant parameters):
def generate_chart_capability(student, df): # canvas sizing plt.figure(figsize=(10, 10)) # plot polar axis (removed redundant projection parameter) ax = plt.subplot(111, polar=True) ax.set_theta_direction(-1) ax.set_theta_offset(np.pi / 1.6) ax.set_xticklabels([]) ax.set_yticklabels([1, 2, 3, 4, 5], size=21) # Compute the width of each bar. In total, we have 2*Pi = 360° width = 2 * np.pi / len(df.index) # Compute the angle each bar is centered on: indexes = list(range(1, len(df.index) + 1)) angles = [element * width for element in indexes] # Compute heights: subtract 1 to offset the bottom=1 anchor heights = df.Value - 1 # <--- Key change # Colour the bars c = ['#054998', '#3660B3', '#5579CF', '#7392EB', '#90ADFF', '#ADC8FF'] # Draw bars anchored at bottom=1 instead of 0 ax.bar(x=angles, height=heights, width=width, color=c, bottom=1, linewidth=2, edgecolor="white") # <--- Key change ax.set_ylim([0, 5]) # Keep full scale visible (0-1 remains empty) # Save the figure plt.savefig('app/static/output/capability_chart_' + student + '.png') # Close the figure plt.clf()
Explanation:
bottom=1: Anchors all bars starting at the 1 mark on the polar axis, leaving the 0-1 inner circle blank.heights = df.Value - 1: Ensures the top of each bar reaches the originaldf.Value(since1 + (df.Value -1) = df.Value), so your data values are accurately represented without shifting.
Solution 2: Overlay a White Circle (For More Control)
If you want to keep your original bar code unchanged but still block the 0-1 region, you can draw a white circle directly over the center. This is useful if you need to maintain the original bar positioning but hide the inner area:
Add this code right after drawing the bars:
# Draw a white circle to create the donut hole circle = plt.Circle((0, 0), 1, transform=ax.transData._b, color='white', zorder=10) ax.add_artist(circle)
Explanation:
- The circle has a radius of 1 (matching your 0-1 range) and is placed at the center
(0,0). zorder=10ensures the circle is drawn on top of the bars, blocking the inner region.- Adjust the radius value if you need a larger or smaller donut hole.
Either solution will give you the clean donut-style polar bar chart you're looking for!
内容的提问来源于stack exchange,提问作者TimothyAURA

