Python matplotlib 甜甜圈图在一个楔形上具有较小的宽度

Python matplotlib donut chart with smaller width on one wedge

我正在尝试重新创建一个圆环图,其中最后一个楔形比其余楔形更薄,如下所示:

但是我找不到办法让最后一个楔子的宽度变小。所以我试着让最后一个楔形与背景颜色相同,并在顶部画一个灰色圆圈。但是我无法在楔形下方绘制圆圈,并在正确的位置使上面的图层透明。

有没有办法让单个楔形变透明,或者以其他方式解决我的问题?

到目前为止,这是我的代码:

import matplotlib.pyplot as plt
donut = [150,10,20,20,30,40]
total = sum(donut)
grey_circle = plt.Circle((0,0),0.965,color='#CCCCCC', lw=1, fill=False)
centre_circle = plt.Circle((0,0),0.93,fc='white')
fig, ax = plt.subplots(figsize=(2, 2), subplot_kw=dict(aspect="equal"))
colors = ['#F8F5EB','#50E3C2','#FF9100','#002776','#C94096','#0071CD' ]
wedges, texts = ax.pie(donut, colors=colors, wedgeprops=dict(width=0.1), startangle=90)
fig.gca().add_artist(grey_circle)
fig.gca().add_artist(centre_circle)
fig.set_facecolor('#F8F5EB')
fig = plt.gcf()
plt.savefig('cirle.png',facecolor=fig.get_facecolor(), edgecolor='none', dpi=300)

plt.show() 

我的结果:

最简单的方法是绘制图表两次,一次用于粗楔形,一次用于细楔形。不绘制的楔形颜色设置为'none'。设置明确的半径将为薄楔形创建正确的尺寸。

使用这种方法,不需要圆圈来隐藏内容。您仍然可以添加一个圆圈以在中心获得不同的颜色。只需添加 zorder=0 以确保圆在饼图后面。

一些代码来说明概念:

import matplotlib.pyplot as plt

donut = [150, 10, 20, 20, 30, 40]

thin_indices = [0]  # indices of all wedges that should be thin
colors = ['#CCCCCC', '#50E3C2', '#FF9100', '#002776', '#C94096', '#0071CD']
colors_thin = [c if i in thin_indices else 'none' for i, c in enumerate(colors)]
colors_thick = [c if i not in thin_indices else 'none' for i, c in enumerate(colors)]
radius = 1
thick_width = 0.1
thin_width = 0.05
radius_thin = radius - 0.5 * (thick_width - thin_width)

fig, ax = plt.subplots(figsize=(2, 2), subplot_kw=dict(aspect="equal"))
ax.pie(donut, radius=radius, colors=colors_thick, wedgeprops=dict(width=thick_width), startangle=90)
ax.pie(donut, radius=radius_thin, colors=colors_thin, wedgeprops=dict(width=thin_width), startangle=90)
centre_circle = plt.Circle((0, 0), radius - thick_width/2, fc='white', zorder=0)
ax.add_artist(centre_circle)

fig.set_facecolor('#F8F5EB')
plt.savefig('cirle.png', facecolor=fig.get_facecolor(), edgecolor='none', dpi=300)

plt.show()