How to have actual values in matplotlib Pie Chart displayed

46,698

Solution 1

Using the autopct keyword

As we know that the percentage shown times the sum of all actual values must be the actual value, we can define this as a function and supply this function to plt.pie using the autopct keyword.

import matplotlib.pyplot as plt
import numpy

labels = 'Frogs', 'Hogs', 'Dogs'
sizes = numpy.array([5860, 677, 3200])
colors = ['yellowgreen', 'gold', 'lightskyblue']

def absolute_value(val):
    a  = numpy.round(val/100.*sizes.sum(), 0)
    return a

plt.pie(sizes, labels=labels, colors=colors,
        autopct=absolute_value, shadow=True)

plt.axis('equal')
plt.show()

Care must be taken since the calculation involves some error, so the supplied value is only accurate to some decimal places.

A little bit more advanced may be the following function, that tries to get the original value from the input array back by comparing the difference between the calculated value and the input array. This method does not have the problem of inaccuracy but relies on input values which are sufficiently distinct from one another.

def absolute_value2(val):
    a  = sizes[ numpy.abs(sizes - val/100.*sizes.sum()).argmin() ]
    return a

Changing text after pie creation

The other option is to first let the pie being drawn with the percentage values and replace them afterwards. To this end, one would store the autopct labels returned by plt.pie() and loop over them to replace the text with the values from the original array. Attention, plt.pie() only returns three arguments, the last one being the labels of interest, when autopct keyword is provided so we set it to an empty string here.

labels = 'Frogs', 'Hogs', 'Dogs'
sizes = numpy.array([5860, 677, 3200])
colors = ['yellowgreen', 'gold', 'lightskyblue']

p, tx, autotexts = plt.pie(sizes, labels=labels, colors=colors,
        autopct="", shadow=True)

for i, a in enumerate(autotexts):
    a.set_text("{}".format(sizes[i]))

plt.axis('equal')
plt.show()

Solution 2

If you're looking to plot a piechart from a DataFrame, and want to display the actual values instead of percentages, you could reformat autopct like so:

values=df['your_column'].value_counts(dropna=True)
plt.pie(<actual_values>, colors = colors, autopct= lambda x: '{:.0f}'.format(x*values.sum()/100), startangle=90)

The example below creates a Donut, but you could play around: (Credit to Kevin Amipara @ https://medium.com/@kvnamipara/a-better-visualisation-of-pie-charts-by-matplotlib-935b7667d77f)

import matplotlib.pyplot as plt

# Pie chart (plots value counts in this case)
labels = df['your_column'].dropna().unique()
actual_values = df['your_column'].value_counts(dropna=True)

#choose your colors
colors = ['#ff9999','#66b3ff','#99ff99','#ffcc99','#fffd55']
 
fig1, ax1 = plt.subplots()

# To denote actual values instead of percentages as labels in the pie chart, reformat autopct
values=df['your_column'].value_counts(dropna=True)
plt.pie(actual_values, colors = colors, autopct= lambda x: '{:.0f}'.format(x*values.sum()/100), startangle=90)


#draw circle (this example creates a donut)
centre_circle = plt.Circle((0,0),0.70,fc='white')
fig = plt.gcf()
fig.gca().add_artist(centre_circle)


# Equal aspect ratio ensures that pie is drawn as a circle
ax1.axis('equal') 

# A separate legend with labels (drawn to the bottom left of the pie in this case) 
plt.legend(labels, bbox_to_anchor = (0.1, .3))

plt.tight_layout()
plt.show()
Share:
46,698
Anthony J
Author by

Anthony J

Updated on July 09, 2022

Comments

  • Anthony J
    Anthony J almost 2 years

    I have a pie chart drawing the values extracted from a CSV file. The proportion of the values are currently displayed with the percentage displayed "autopct='%1.1f%%'". Is there a way to display the actual values which are represented in the dataset for each slice.

    #Pie for Life Expectancy in Boroughs
    import pandas as pd
    import matplotlib
    import matplotlib.pyplot as plt
    
    # show plots inline
    %matplotlib inline
    
    # use ggplot style
    matplotlib.style.use('ggplot')
    
    #read data
    lifeEx = pd.read_csv('LEpie.csv')
    
    #Select columns
    df = pd.DataFrame()
    df['LB'] = lifeEx[['Regions']]
    df['LifeEx'] = lifeEx[['MinLF']]
    colorz = ['#B5DF00','#AD1FFF', '#BF1B00','#5FB1FF','#FFC93F']
    exploda = (0, 0, 0, 0.1, 0)
    
    
    #plotting
    plt.pie(df['LifeEx'], labels=df['LB'], colors=colorz, autopct='%1.1f%%', explode = exploda, shadow = True,startangle=90)
    
    #labeling
    plt.title('Min Life expectancy across London Regions', fontsize=12)