Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional removal of labels in Matplotlib pie chart

I have the following code:

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(123456)
import pandas as pd

df = pd.DataFrame(3 * np.random.rand(4, 4), index=['a', 'b', 'c', 'd'], 
                  columns=['x', 'y','z','w'])

plt.style.use('ggplot')
colors = plt.rcParams['axes.color_cycle']

fig, axes = plt.subplots(nrows=2, ncols=3)
for ax in axes.flat:
    ax.axis('off')

for ax, col in zip(axes.flat, df.columns):
    ax.pie(df[col], labels=df.index, autopct='%.2f', colors=colors)
    ax.set(ylabel='', title=col, aspect='equal')

axes[0, 0].legend(bbox_to_anchor=(0, 0.5))

fig.savefig('your_file.png') # Or whichever format you'd like
plt.show()

Which produce the following:

enter image description here

My question is, how can I remove the label based on a condition. For example I'd only want to display labels with percent > 20%. Such that the labels and value of a,c,d won't be displayed in X, etc.

like image 848
neversaint Avatar asked Dec 02 '15 05:12

neversaint


People also ask

How do you hide labels on a pie chart in Python?

MatPlotLib with Python Plot a pie chart using pie() method. To hide the label on the left side in matplotlib, we can use plt. ylabel("") with ablank string.

How do you avoid overlapping of labels and Autopct in a Matplotlib pie chart?

To avoid overlapping of labels and autopct in a matplotlib pie chart, we can follow label as a legend, using legend() method.


1 Answers

The autopct argument from pie can be a callable, which will receive the current percentage. So you only would need to provide a function that returns an empty string for the values you want to omit the percentage.

def my_autopct(pct):
    return ('%.2f' % pct) if pct > 20 else ''

ax.pie(df[col], labels=df.index, autopct=my_autopct, colors=colors)

If you need to parametrize the value on the autopct argument, you'll need a function that returns a function, like:

def autopct_generator(limit):
    def inner_autopct(pct):
        return ('%.2f' % pct) if pct > limit else ''
    return inner_autopct

ax.pie(df[col], labels=df.index, autopct=autopct_generator(20), colors=colors)

For the labels, the best thing I can come up with is using list comprehension:

for ax, col in zip(axes.flat, df.columns):                                                             
    data = df[col]                                                                                     
    labels = [n if v > data.sum() * 0.2 else ''
              for n, v in zip(df.index, data)]                       

    ax.pie(data, autopct=my_autopct, colors=colors, labels=labels)

Note, however, that the legend by default is being generated from the first passed labels, so you'll need to pass all values explicitly to keep it intact.

axes[0, 0].legend(df.index, bbox_to_anchor=(0, 0.5))
like image 193
memoselyk Avatar answered Sep 29 '22 21:09

memoselyk