Popular Tags

Matplotlib: Nested Pie Charts

In this tutorial, we’ll create nested pie charts (double donut charts) with the help of Matplotlib and Pandas libraries.

Matplotlib: Nested Pie Charts


  1. Prerequisites
  2. Getting Started
  3. Data Preparation
  4. Plotting

A multi-level donut chart (a nested pie chart) is useful when you have data in minor categories that make part of a larger category or when you want to compare similar data from various periods and show the result in one chart.

You can also read our article Matplotlib Pie Charts to learn how to create an ordinary pie chart as well as a series of donut charts displayed in one figure.


To create a nested pie chart, we’ll need the following:

  • Python installed on your machine
  • Pip: package management system (it comes with Python)
  • Jupyter Notebook: an online editor for data visualization
  • Pandas: a library to prepare data for plotting
  • Matplotlib: a plotting library

You can download the latest version of Python for Windows on the official website.

To get other tools, you’ll need to install recommended Scientific Python Distributions. Type this in your terminal:

pip install numpy scipy matplotlib ipython jupyter pandas sympy nose

Getting Started

Create a folder that will contain your notebook (e.g. “mpl-nested”) and open Jupyter Notebook by typing this command in your terminal (don’t forget to change the path):

cd C:\Users\Shark\Documents\code\mpl-nested
py -m notebook

This will automatically open the Jupyter home page at http://localhost:8888/tree. Click on the “New” button in the top right corner, select the Python version installed on your machine, and a notebook will open in a new browser window.

In the first line of the notebook, import all the necessary libraries:

import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd
%matplotlib notebook

You’ll need the last line (%matplotlib notebook) to display plots in input cells.

Data Preparation

We’ll create a nested donut chart showing crime categories in the London borough of Croydon. We’ll use a .csv file for plotting. You can download the “London Crime Data, 2008–2016” dataset on Kaggle (london_crime_by_lsoa.csv).

On the second line in your Jupyter notebook, type this code to read the file:

df = pd.read_csv('london_crime_by_lsoa.csv')

This will show the first 5 lines of the .csv file:

Pandas reading .csv file

Next, prepare data for plotting. For simplicity, we won’t use the “value” column and will focus on the “borough”, “major_category” and “minor_category” columns instead.

In the code below, we’re selecting columns we need, grouping values, and creating a pivot table:

df = df[['borough', 'major_category', 'minor_category']]
df = df.groupby(['borough', 'major_category', 'minor_category']).size().reset_index()
df = pd.pivot_table(df, index=['borough'], columns=['major_category', 'minor_category'])
df = df.iloc[7].reset_index()
del df['level_0']
df = df.pivot_table('Croydon', ['major_category', 'minor_category'])

Here’s the output:

Pandas pivot table


We’ll need the following variables for plotting:

facecolor = '#eaeaf2'
font_color = '#525252'
hfont = {'fontname':'Calibri'}
labels = ['Burglary','Criminal Damage','Drugs','Fraud or Forgery' ,'Other Notifiable Offences','Robbery','Sexual Offences','Theft and Handling','Violence Against the Person']
size = 0.3
vals = df['Croydon']
# Major category values = sum of minor category values
group_sum = df.groupby('major_category')['Croydon'].sum()

We’ll create a labeled multi-level donut chart in 5 steps. All the code snippets below should be placed inside one cell in your Jupyter Notebook.

1. Create a figure and subplots

fig, ax = plt.subplots(figsize=(10,6), facecolor=facecolor)

figsize=(10,6) creates a 1000 × 600 px figure.

2. Create colors

a,b,c,d,e,f,g,h,i = [plt.cm.winter, plt.cm.cool, plt.cm.spring, plt.cm.copper, plt.cm.bone, plt.cm.gist_heat, plt.cm.pink, plt.cm.summer, plt.cm.autumn]

outer_colors = [a(.6), b(.6), c(.6), d(.6), e(.6), f(.6), g(.6), h(.6), i(.6)]
inner_colors = [a(.5), a(.4), 
                b(.5), b(.4), b(.3), b(.2),
                c(.5), c(.4), c(.3),
                d(.5), d(.4),
                e(.5), e(.4),
                f(.5), f(.4),
                g(.5), g(.4),
                h(.7), h(.6), h(.5), h(.4), h(.3), h(.2), h(.1), h(5),
                i(.7), i(.6), i(.5), i(.4), i(.3), i(.2), i(.1)]

Here, 9 variables from a to i correspond to the number of the outer circle’s sections (which are major categories of crime). 

plt.cm.winter, plt.cm.cool, etc. are Matplotlib colormaps. You can read about them in Matplotlib documentation.

a(.6), b(.5), c(.4), etc. correspond to color variants or opacity levels.

The number of a to i variables inside inner_colors corresponds to the number of the inner circle’s sections inside each of the outer circle’s sections.

3. Draw pies

       wedgeprops=dict(width=size, edgecolor='w'))

       radius=1-size, # size=0.3
       wedgeprops=dict(width=size, edgecolor='w'))

wedgeprops=dict() would create a donut (a pie chart with a hole in the center). Don’t use this parameter, and you’ll get a pie chart instead of a donut chart.

4. Set a title

ax.set_title('Crime categories in Croydon', fontsize=18, pad=15, color=font_color, **hfont)

pad=15 would create padding under the title.

5. Save the chart as a picture

filename = 'mpl-nested-pie'
plt.savefig(filename+'.png', facecolor=facecolor)

You might need to repeat facecolor in savefig(). Otherwise, plt.savefig might ignore it.

That’s it, our Matplotlib nested pie chart is ready. You can download the notebook on GitHub to get the full code.

Read also:

→ Matplotlib Pie Charts

→ Matplotlib: Bidirectional Bar Chart