将百分比标签添加到三级甜甜圈图

时间:2019-12-25 21:32:01

标签: python matplotlib

我想为三层甜甜圈图中的每个标签和层添加百分比值。

以下代码适当地生成三层甜甜圈图和图例。但是,它弄乱了百分比值的显示(请参阅此问题底部的输出图)。

当前在堆栈溢出或其他地方的解决方案仅适用于将百分比值添加到饼图/甜甜圈图(例如:How do I use matplotlib autopct? ),但是我在饼图/甜甜圈图上有三个层次/级别。我的代码如下:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
fig.set_figheight(7)
fig.set_figwidth(22)

ax1 = fig.add_subplot(121)

first_labels = ["Bonjovi", "Superman", "Darius_royale", "Stargazer_1991_viz", "Obligatory_Vis1", "Gertrude", 'Trimbel', "Olio", "Iniwaka"]
first_sizes = [2000, 300, 200, 100, 100, 150, 40, 30, 700]

second_sizes = [1000, 200, 200, 400, 500, 40, 1, 1, 1000]

third_sizes = [500, 300, 400, 500, 400, 100, 5, 2, 800]

flatui = (sns.diverging_palette(20, 250, n=8))

bigger = plt.pie(first_sizes, colors=flatui, startangle=90, frame=True, radius = 1,
                 wedgeprops={'edgecolor':'k'}, autopct = '%1.1%%f')

smaller = plt.pie(second_sizes, colors=flatui, radius=0.9, startangle=90,
                 wedgeprops={'edgecolor':'k'}, autopct = '%1.1%%f')

smallest = plt.pie(third_sizes, colors=flatui, radius=0.8, startangle=90, 
                  wedgeprops={'edgecolor':'k'}, autopct = '%1.1%%f')

centre_circle = plt.Circle((0, 0), 0.7, color='white', linewidth=0)

plt.gca().add_artist(centre_circle)

# add legend to current ax:
plt.gca().legend(first_labels, loc='center right', bbox_to_anchor=(1,0,.4,1), frameon = True)

plt.show();

以上代码的结果如下:enter image description here

有人可以指导我如何获取在每个甜甜圈圈中整齐显示的百分比值吗?

1 个答案:

答案 0 :(得分:1)

总结一下我的评论,这是我获得更好图形输出的代码,并且我相信您在寻找什么:

import matplotlib.pyplot as plt
import numpy as np


# Example function that you can call from pie(autopct=autopct)
def autopct(pct):
    if pct > 0.5:
        return f'{pct:.2f}%'
    else:
        return ''


fig = plt.figure()
fig.set_figheight(7)
fig.set_figwidth(22)

ax1 = fig.add_subplot(121)

first_labels = (
    'Bonjovi',
    'Superman',
    'Darius Royale',
    'Stargazer 1991 Viz',
    'Obligatory Vis1',
    'Gertrude',
    'Trimbel',
    'Olio',
    'Iniwaka'
)
first_sizes = (2000, 300, 200, 100, 100, 150, 40, 30, 700)
second_sizes = (1000, 200, 200, 400, 500, 40, 1, 1, 1000)
third_sizes = (500, 300, 400, 500, 400, 100, 5, 2, 800)

flatui = (sns.diverging_palette(20, 250, n=8))

bigger = plt.pie(
    first_sizes,
    colors=flatui,
    startangle=90,
    frame=True,
    radius=1,
    wedgeprops={'edgecolor':'k'},
#    autopct='%.2f%%',
    autopct=autopct,
    pctdistance=1
)

smaller = plt.pie(
    second_sizes,
    colors=flatui,
    radius=0.9,
    startangle=90,
    wedgeprops={'edgecolor':'k'},
#    autopct='%.2f%%',
    autopct=autopct,
    pctdistance=.9
)

smallest = plt.pie(
    third_sizes,
    colors=flatui,
    radius=0.8,
    startangle=90,
    wedgeprops={'edgecolor':'k'},
#    autopct='%.2f%%',
    autopct=autopct,
    pctdistance=.8
)

centre_circle = plt.Circle((0, 0), 0.7, color='white', linewidth=0)

plt.gca().add_artist(centre_circle)

# add legend to current ax:
plt.gca().legend(
    first_labels,
    loc='center right',
    bbox_to_anchor=(1,0,.4,1),
    frameon=True
)

plt.show()

您需要调整pctdistance,直到对结果满意为止。

编辑:

经过研究,我写了这个更好的(IMHO)版本:

import matplotlib.pyplot as plt


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

sizes = dict(
    first = (2000, 300, 200, 100, 100, 150, 40, 30, 700),
    second = (1000, 200, 200, 400, 500, 40, 1, 1, 1000),
    third = (500, 300, 400, 500, 400, 100, 5, 2, 800)
)

percentiles = dict(
    first = [x*100/sum(sizes['first']) for x in sizes['first']],
    second = [x*100/sum(sizes['second']) for x in sizes['second']],
    third = [x*100/sum(sizes['third']) for x in sizes['third']]
)

labels = dict(
    first = [f"{x:.2f}%" if x >.5 else '' for x in percentiles['first']],
    second = [f"{x:.2f}%" if x >.5 else '' for x in percentiles['second']],
    third = [f"{x:.2f}%" if x >.5 else '' for x in percentiles['third']]
)

width = 0.35
radius = 1.5

first, _ = ax.pie(
    sizes['first'],
    startangle=90,
    radius=radius,
    labeldistance=.9,
    labels=labels['first'],
    rotatelabels=True
)

second, _ = ax.pie(
    sizes['second'],
    radius=radius - width,
    startangle=90,
    labeldistance=.9,
    labels=labels['second'],
    rotatelabels=True
)

third, _ = ax.pie(
    sizes['third'],
    radius=radius - 2 * width,
    startangle=90,
    labeldistance=.9,
    labels=labels['third'],
    rotatelabels=True
)

plt.setp(first + second + third, width=width, edgecolor='white')

plt.show()