Search code examples
pythonmatplotlibpie-chart

How to select only one plot in a legend of a double plot pie?


I have created two plt.pie in the shape of donuts. The 1st encompassing the 2nd, and the 2nd encompassing the void, a white hole. I would like to create a plt.legend () but only including the second plot. I can't seem to select only the second one.

In my caption I want to display each labels of labels_origin with the percentage they represent, as well as the correct color code.

It seems here that he is mixing the colors of my 2 plots.

Anyone have a solution please?

import matplotlib.pyplot as plt

labels = ["Part pertes", "Part humaine", "Part animale", "Part autres utilisations", "Part semences", "Part traitements"]
sizes = [part_pertes , part_humaine , part_animale, part_autres_util, part_semences, part_traitements]

labels_origine = ["Part pertes - Animale", "Part pertes - Végétale",
                  "Part humaine - Animale", "Part humaine - Végétale",
                  "Part animale - Animale", "Part animale - Végétale",
                  "Part autres utilisations - Animale", "Part autres utilisations - Végétale",
                  "Part semences - Animale", "Part semences - Végétale",
                  "Part traitements - Animale", "Part traitements - Végétale"]
sizes_origine = [part_pertes_prod_anim, part_pertes_prod_veget,
                 part_humaine_prod_anim , part_humaine_prod_veget,
                 part_animale_prod_anim, part_animale_prod_veget,
                 part_autres_util_prod_anim,  part_autres_util_prod_veget,
                 part_semences_prod_anim, part_semences_prod_veget,
                 part_traitements_prod_anim,  part_traitements_prod_veget]

size = 0.3
fig, ax = plt.subplots(figsize=(10, 10))

# Couleurs
colors = ["#ff5959", "#2693ff", "#59FF59", "#FF8C19", "#3D3DC8", "#ffb3e6"]
colors_origine = ['#ff9999', "#ffd8d8", "#66b3ff", "#a5d2ff", "#99ff99", "#D8FFD8",
                  "#FFAC59", "#FFCB98", "#c2c2f0", "#7B7BDC", "#ffb3e6", "#FFF2FA" ]

#Plot
plot1 = plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=45, pctdistance=0.85,
        textprops={"fontsize":14}, radius=1, wedgeprops=dict(width=size, edgecolor='w'))

plot2 = plt.pie(sizes_origine, colors=colors_origine, startangle=45, pctdistance=0.85,
        radius=1-size, wedgeprops=dict(width=size, edgecolor='w'))

plt.axis('equal')
plt.tight_layout()

total=sum(sizes_origine)

plt.legend(loc=0,
    labels=['%s, %1.1f%%' % (
        l, (float(s) / total) * 100) for l, s in zip(labels_origine, sizes_origine)],
    bbox_to_anchor=(1.7, 1),
    prop={'size': 14},
    title="Origine des parts",
    title_fontsize=16)

plt.title("Répartition des différentes parts de la disponibilité intérieure mondiale", fontsize=20)
plt.show()

Screenshot of my double plot pie


Solution

  • A quick fix could be manually setting the legend handles colors. You need to get the current axis with .gca(), then get the legend from the axis and manually set the color by iterating over them (the code needs to be inserted after the legend call):

    ax = plt.gca()
    leg = ax.get_legend()
    for index, color_origine in enumerate(colors_origine):
        leg.legendHandles[index].set_color(color_origine)
    

    Working example with random values:

    import matplotlib.pyplot as plt
    
    labels = ["Part pertes", "Part humaine", "Part animale", "Part autres utilisations", "Part semences", "Part traitements"]
    sizes = [15 , 38 , 200, 10, 25, 44]
    
    labels_origine = ["Part pertes - Animale", "Part pertes - Végétale",
                      "Part humaine - Animale", "Part humaine - Végétale",
                      "Part animale - Animale", "Part animale - Végétale",
                      "Part autres utilisations - Animale", "Part autres utilisations - Végétale",
                      "Part semences - Animale", "Part semences - Végétale",
                      "Part traitements - Animale", "Part traitements - Végétale"]
    sizes_origine = [11, 45,
                     100 , 12,
                     24, 3,
                     55,  87,
                     34, 43,
                     22,  77]
    
    size = 0.3
    fig= plt.figure(figsize=(10, 10))
    
    
    # Couleurs
    colors = ["#ff5959", "#2693ff", "#59FF59", "#FF8C19", "#3D3DC8", "#ffb3e6"]
    colors_origine = ['#ff9999', "#ffd8d8", "#66b3ff", "#a5d2ff", "#99ff99", "#D8FFD8",
                      "#FFAC59", "#FFCB98", "#c2c2f0", "#7B7BDC", "#ffb3e6", "#FFF2FA" ]
    
    #Plot
    plot1 = plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=45, pctdistance=0.85,
            textprops={"fontsize":14}, radius=1, wedgeprops=dict(width=size, edgecolor='w'))
    
    plot2 = plt.pie(sizes_origine, colors=colors_origine, startangle=45, pctdistance=0.85,
            radius=1-size, wedgeprops=dict(width=size, edgecolor='w'))
    
    plt.axis('equal')
    plt.tight_layout()
    
    total=sum(sizes_origine)
    
    plt.legend(loc=0,
        labels=['%s, %1.1f%%' % (
            l, (float(s) / total) * 100) for l, s in zip(labels_origine, sizes_origine)],
        bbox_to_anchor=(1.7, 1),
        prop={'size': 14},
        title="Origine des parts",
        title_fontsize=16)
    
    plt.title("Répartition des différentes parts de la disponibilité intérieure mondiale", fontsize=20)
    
    # THIS ↓↓↓↓↓
    ax = plt.gca()
    leg = ax.get_legend()
    for index, color_origine in enumerate(colors_origine):
        leg.legendHandles[index].set_color(color_origine)
    
    plt.show()
    

    which outputs:

    enter image description here