Matplotlib | Donut graph! Percentage % in the center (pie, text)

A pie chart is often used to display data proportions, but for a more modern design, a doughnut graph is sometimes used by hollowing out the center of the pie chart.

This article explains how to plot donut and double donut graphs in Matplotlib

Detailed instructions are also provided on how to customize the donut graph legend, labels, percentages, changing element coordinates, colors, colormaps, thickness, text, and more.

Please refer to the following article regarding pie charts

Table of Contents

Options for doughnut graphs

In Matplotlib, donut graphs are drawn with the Axes.pie function.

Axes.pie
Parameters
  • x (1D array-like) : The wedge sizes.
  • explode (array-like) : Percentage distance of each element from the center of the graph
  • labels (list) : A sequence of strings providing the labels for each wedge
  • colors (color) : A sequence of colors through which the pie chart will cycle. If None, will use the colors in the currently active cycle.
  • autopct (None or str or callable) : autopct is a string or function used to label the wedges with their numeric value. If autopct is a format string, the label will be fmt % pct.
  • pctdistance (float) : The relative distance along the radius at which the text generated by autopct is drawn.
  • shadow (bool) : whether to draw a shadow beneath the pie.
  • labeldistance (float) : The relative distance along the radius at which the labels are drawn. 
  • counterclock (bool) : Specify fractions direction, clockwise or counterclockwise.
  • startangle (float)The angle by which the start of the pie is rotated, counterclockwise from the x-axis.
  • radius (float) : The radius of the pie.
  • wedgeprops (dict) : Dict of arguments passed to each patches.Wedge of the pie.
  • textprops (dict) : Dict of arguments to pass to the text objects.
  • center ((float, float)) : The coordinates of the center of the chart.
  • frame (bool) : Plot Axes frame with the chart if true.
  • rotatelabels (bool) : Rotate each label to the angle of the corresponding slice if true.
  • normalize (bool) : When True, always make a full pie by normalizing x so that sum(x) == 1.
  • radius (float) : The radius of the pie.
Returns
  • patches (list) : A sequence of matplotlib.patches.Wedge instances
  • texts (list) : A list of the label Text instances.
  • autotexts (list) : A list of Text instances for the numeric labels.
Official Documentation

Basic donut graph (wedgeprops, color)

Draws a donut graph with the center portion hollowed out from a pie chart.

The donut graph is drawn by changing the width of the pie chart using the wedgeprops argument of the Axes.pie function.

Width of the elements (wedgeprops)

The argument wedgeprops is specified as a dictionary type, {'width': 0.3}.

The following tabs explain the code and flowchart

import matplotlib.pyplot as plt
import numpy as np

# step1 Create data
width = 0.3
vals = [40, 60]

# step2 Create graph frames
fig, ax = plt.subplots()

# step3 Plot a donut chart
ax.pie(vals, startangle=90,
        # Pie Chart Width
        wedgeprops={'width':width}
)
ax.set_title('Donut chart')

plt.show()

Colors of the elements (colors)

Colors of the elements are specified by colors=array.

We used a color gradient with a colormap called Blues.

The color map can change color according to the data values.

The function creates an RGBA array of the minimum to maximum values of the data.

colors.Colormap
Parameters
  • name (str) : Name of the colormap
  • N (int) : Number of RGB quantization levels
Returns
  • Data is scalar : RGBA Array (tuple)
  • Data is arrayed : RGBA Array (Data array + 4 rows)
Official Documentation
import matplotlib.pyplot as plt
import numpy as np

# step1 Create data
width = 0.3
vals = [40, 60]
# step1.1 Create a colormap
cmap = plt.get_cmap('Blues')
colors = cmap(np.linspace(0.2, 0.7, len(vals)))

# step2 Create graph frames
fig, ax = plt.subplots()

# step3 Plot a donut chart
ax.pie(vals, startangle=90,
        # Donut Chart Width
        wedgeprops={'width':width},
        # Add colors
        colors=colors
)
ax.set_title('Donut chart')
plt.show()

Percentage of circle center (Axes.text)

The Axes.text function displays a percentage % or strings in the center of the doughnut graph.

The following is a list of options for the Axes.text function

Axes.text
Parameters
  • x, y (float) : The position to place the text. By default, this is in data coordinates.
  • s (str) : The text
  • fontdict (dict) : A dictionary to override the default text properties.
  • fontsize (float or size) : Font size. Numeric or size specification. {'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'}
  • horizontalalignment or ha (‘left’, ‘center’, ‘right’) : Horizontal adjustment
  • verticalalignment or va (‘baseline’, ‘bottom’, ‘center’, ‘center_baseline’, ‘top’) : Vertical adjustment
  • color or c (color) : Text Color
Returns
Official Documentation

Show Percentage % (fontsize)

Specify coordinates (x, y) = (0, 0) and strings (s) = 60% + Donut Chart as arguments to Axes.text.

In addition, we set font size = 20

# step4 Add text
ax.text(0, 0, r'60%'+'\nDonut Chart', fontsize=20)

Place a percentage % (horizontalalignment, verticalalignment)

In the Show Percentage %, the position of the displayed text was not centered.

horizontalalignment='center' for horizontal, verticalalignment='center' for vertical

It can also be abbreviated as horizontalalignment→ha, verticalalignment→va.

# step4 Add text
ax.text(0, 0, r'60%'+'\nDonut Chart', fontsize=20, 
        horizontalalignment='center', 
        verticalalignment='center'
)

Modern design donut graph (color)

Separate the percentage from the rest of the text and highlight only the percentage.

First, use two Axes.text functions, one for the percentage text you want to emphasize and one for the rest of the text.

Utilizing the verticalalignment of Place a Percentage, the top text is set to bottom and the bottom text to top, there is no interference at any font size.

# step1.1 Create a colormap
color_text = cmap(0.7)

# step4 Add text
ax.text(0, 0, r'60%', color=color_text, fontsize=32, fontweight='medium',
        horizontalalignment='center', verticalalignment='bottom')
ax.text(0, 0, r'Donut Chart', color=color_text, fontsize=20, 
        horizontalalignment='center', verticalalignment='top')

Legend and numpy.array (Axes.legend)

This section explains how to display and arrange a legend on a donut graph.

In addition, the ndarray of numpy.array is used for graph data from this chapter.

Axes.legend
Parameters
  • handles (list of Artist) : A list of Artists (lines, patches) to be added to the legend.
  • labels (list of str) : A list of labels to show next to the artists.
  • loc (list of str or float) : A list of labels to show next to the artists.'best',upper left''upper right''lower left''lower right','right', 'center left','center right','upper center','lower center','center'
  • bbox_to_anchor (BboxBase) : Box that is used to position the legend in conjunction with loc.
Returns
Official Documentation

Legend (loc, bbox_to_anchor)

The prepared array is ndarray of numpy.array, a 2-dimensional array with 4 rows and 2 columns.
The sum of the arrays is calculated for each row, and the result is a 1D array of 4 elements, which is used for the graph.

The legend is positioned in the center left using loc='center left' and bbox_to_anchor=(1, 0, 0.5, 1) to move the legend by one graph pixel to the right in the x direction.

A detailed explanation of the legend will be provided in another article.

import matplotlib.pyplot as plt
import numpy as np

# step1 Create label and data
labels = ['A', 'B', 'C', 'D']
width = 0.3
vals = np.array([[60, 32], [40, 35], [29, 10], [18, 5]])
# step2 Create graph frames
fig, ax = plt.subplots()
# step3 Plot a donut chart
ax.pie(vals.sum(axis=1), labels=labels, 
        wedgeprops={'width':width},
        startangle=90
)

ax.set_title('Donut chart with a legend')
# Legend
ax.legend(loc='center left', bbox_to_anchor=(1, 0, 0.5, 1))

plt.show()

Direction of rotation (counterclock)

The rotation direction of the pie chart can be clockwise by setting counterclock=False in the Axes.pie function.

# step3 Plot a donut chart
ax.pie(vals.sum(axis=1), labels=labels,
        wedgeprops={'width':width},
        startangle=90, 
        counterclock=False
)

Start position of circle (startangle)

The circumferential starting position of the element is specified as an angle in startangle.

The basic starting position is at (x, y) = (1, 0)

# step3 Plot a donut chart
ax.pie(vals.sum(axis=1), labels=labels,
        wedgeprops={'width':width},
        startangle=0, 
        counterclock=False
)

Numeric labels for each group (autopct, pctdistance)

Numeric labels can be displayed by specifying autopct as an argument to Axes.pie.

pctdistance can also change the position of the numerical labels.

# step3 Plot a donut chart
ax.pie(vals.sum(axis=1), labels=labels, startangle=90, counterclock=False,
        wedgeprops={'width':width},
        # Display of numeric labels
        autopct='%.1f%%', 
        # Position of numeric labels
        pctdistance=0.85,
)

Double donut graph (radius)

When data is divided into large and medium categories, the doughnut graph is doubled so that each element can be viewed in detail.

In Matplotlib, the inner donut graph is drawn by a combination of reducing the radius + separating the colors in the color map

The colormap used is tab20c, with a significant color change for each of the four.

Outer donut chart

It is drawn in the same way as the donut charts in the previous chapters.

Since there are four sets of colors per colormap, the array is passed to the colormap in multiples of four to create a color array of just the main colors.
cmap(np.arange(vals.shape[0])*4)=cmap([0, 4, 8, 12])

# step1 Create labels and data
labels = ['A', 'B', 'C', 'D']
width = 0.3
vals = np.array([[60, 32], [40, 35], [29, 10], [18, 5]])
# step2 Create graph frames
fig, ax = plt.subplots()
# step3 Create a colormap
cmap = plt.colormaps['tab20c']
# Color of an outer donut chart
outer_colors = cmap(np.arange(vals.shape[0])*4)
# vals.shape[0]=nrows
# np.arange(4)=[0, 1, 2, 3]
# cmap([0, 4, 8, 12])

# step4 Plot an outer donut chart
ax.pie(vals.sum(axis=1), radius=1, startangle=90, counterclock=False,
    labels=labels,
    autopct='%.0f%%', 
    pctdistance=1.15-width, 
    wedgeprops={'width':width, 'edgecolor':'white'},
    colors=outer_colors)

plt.show()

Inner donut chart (radius)

Since the main color is a multiple of 4, assign a multiple of 4 to each row and +1 to each column.
cmap([1, 2, 5, 6, 9, 10, 13, 14])

Data is made into one-dimensional array by numpy.flatten

radius=1-width reduces the radius of the graph by the width of the outer graph

# step3 Create a colormap
cmap = plt.colormaps['tab20c']
# Color an inner donut chart
inner_colors = cmap([i*4+j+1 for i, vs in enumerate(vals) for j in range(vs.size)])
# i*4: Assign multiples of 4 to each row
# j+1: Add +1 per column

# step5 Plot an inner donut chart
ax.pie(vals.flatten(), radius=1-width, startangle=90, counterclock=False,
    autopct='%.0f%%', 
    pctdistance=1.1-width, 
    wedgeprops={'width':width, 'edgecolor':'white'},
    colors=inner_colors)

double donut graph

A double donut graph plots the outer doughnut graph and the inner doughnut graph together.

The following tabs explain the code and flowchart.

# step1 Create labels and data
labels = ['A', 'B', 'C', 'D']
width = 0.3
vals = np.array([[60, 32], [40, 35], [29, 10], [18, 5]])
# step2 Create graph frames
fig, ax = plt.subplots()
# step3 Create a colormap
cmap = plt.colormaps['tab20c']
outer_colors = cmap(np.arange(vals.shape[0])*4)
inner_colors = cmap([i*4+j+1 for i, vs in enumerate(vals) for j in range(vs.size)])

# step4 Plot an outer donut chart
ax.pie(vals.sum(axis=1), radius=1, startangle=90, counterclock=False,
    labels=labels,
    autopct='%.0f%%', 
    pctdistance=1.15-width, 
    wedgeprops={'width':width, 'edgecolor':'white'},
    colors=outer_colors)

# step5 Plot an inner donut chart
ax.pie(vals.flatten(), radius=1-width, startangle=90, counterclock=False,
    autopct='%.0f%%', 
    pctdistance=1.1-width, 
    wedgeprops={'width':width, 'edgecolor':'white'},
    colors=inner_colors)

ax.set_title('tab20c in double donut chart')
ax.legend(loc='center left', bbox_to_anchor=(1, 0, 0.5, 1))
plt.show()

References

Donut pie chart

Labeled pie charts and donut pie charts

I hope you will share it with me!

Comments

To comment

Table of Contents