Matplotlib Multiple Circle Plots

Creating multiple circles in Matplotlib is one of those tasks that sounds simple until you actually try to align them perfectly.

I have spent years building dashboards and data visualizations in Python, and I can tell you that there are at least three ways to do this. Each has its own place depending on whether you are drawing a few specific shapes or plotting thousands of data points.

In this tutorial, I will show you how to master multiple circle plots in Matplotlib using the best methods I’ve found.

How to Plot Multiple Circles in Matplotlib

When I first started with Matplotlib, I thought I could just call a “circle” function and be done. It turns out you have a few powerful options.

I usually stick to these three techniques:

  1. Adding individual Circle patches for precision.
  2. Using a PatchCollection when performance matters (like plotting hundreds of circles).
  3. Using the scatter method for data-driven bubbles.

Let’s dive into each one with some real-world examples.

Method 1: Use Matplotlib Patches (The Precise Way)

If you need to place a few circles at specific locations, maybe to highlight key cities on a map or specific zones in a warehouse, using patches.Circle is the way to go.

I like this method because it gives you total control over every single circle’s properties.

In this example, let’s visualize three major tech hubs in the USA: San Francisco, Austin, and New York.

import matplotlib.pyplot as plt

# Initialize the figure and axis
fig, ax = plt.subplots(figsize=(8, 6))

# Creating individual circles (x, y), radius
# Let's assume these are coordinates on a simplified grid
sf_hub = plt.Circle((2, 8), 0.5, color='blue', alpha=0.6, label='San Francisco')
austin_hub = plt.Circle((5, 3), 0.5, color='orange', alpha=0.6, label='Austin')
ny_hub = plt.Circle((8, 7), 0.5, color='green', alpha=0.6, label='New York')

# Adding circles to the axes
ax.add_patch(sf_hub)
ax.add_patch(austin_hub)
ax.add_patch(ny_hub)

# Important: Set the limits so the circles are visible
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)

# Keep the aspect ratio equal so circles look like circles (not ovals!)
ax.set_aspect('equal', adjustable='datalim')

plt.title("Tech Hub Locations (Simplified US Grid)")
plt.legend()
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()

You can see the output in the screenshot below.

Matplotlib Multiple Circle Plots

When you use this method, remember to call ax.set_aspect(‘equal’). I can’t tell you how many times I’ve seen “circles” look like squashed eggs because the axes were scaled differently.

Method 2: Use PatchCollection (The Efficient Way)

When I’m working with a large dataset, say, visualizing population density across dozens of US counties, adding patches one by one becomes slow.

That is where PatchCollection comes in. It groups all your circles into a single object, which Matplotlib can render much faster.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from matplotlib.collections import PatchCollection

# Generating random data for 50 "Target Areas" across a region
np.random.seed(42)
num_circles = 50
x_coords = np.random.rand(num_circles) * 100
y_coords = np.random.rand(num_circles) * 100
radii = np.random.rand(num_circles) * 5

fig, ax = plt.subplots(figsize=(10, 8))

circles = []
for x, y, r in zip(x_coords, y_coords, radii):
    # Create the circle objects and store them in a list
    circle = Circle((x, y), r)
    circles.append(circle)

# Create a collection and apply a colormap
collection = PatchCollection(circles, cmap='magma', alpha=0.5)
collection.set_array(radii)  # Color them based on size

ax.add_collection(collection)

# Set plot limits
ax.set_xlim(0, 110)
ax.set_ylim(0, 110)
ax.set_aspect('equal')

plt.colorbar(collection, label='Area Size Indicator')
plt.title("Regional Population Density Mockup")
plt.xlabel("West-East Distance (Miles)")
plt.ylabel("South-North Distance (Miles)")
plt.show()

You can see the output in the screenshot below.

Multiple Circle Plots in Matplotlib

I find this method perfect for “Heat Map” style visualizations where the circles represent specific physical areas.

Method 3: The Scatter Plot Trick (The Fast Way)

Sometimes you don’t need “true” geometry; you just want bubbles that scale with your data. This is what I use for most data science projects.

The plt.scatter function is incredibly fast. However, there is a catch: the size parameter s is in “points squared,” not data units. If you zoom in, the circles stay the same size on your screen.

Here is how I use it to compare GDP growth across different US sectors.

import matplotlib.pyplot as plt

# Data: Sector, GDP Contribution ($B), Growth Rate (%)
sectors = ['Tech', 'Healthcare', 'Finance', 'Retail', 'Energy']
gdp = [2500, 1800, 2100, 1200, 900]
growth = [15, 8, 5, 3, -2]

# Scale GDP for bubble size
bubble_sizes = [g * 2 for g in gdp]

plt.figure(figsize=(10, 6))

# Plotting bubbles
scatter = plt.scatter(sectors, growth, s=bubble_sizes, 
                      c=growth, cmap='RdYlGn', alpha=0.7, edgecolors='black')

plt.axhline(0, color='black', linewidth=1) # Baseline
plt.ylabel("Growth Rate (%)")
plt.title("US Economic Sector Analysis (Bubble Size = GDP)")
plt.grid(axis='y', linestyle='--', alpha=0.7)

# Adding a colorbar to show growth intensity
plt.colorbar(scatter, label='Growth Percentage')

plt.show()

You can see the output in the screenshot below.

Multiple Circle Plots Matplotlib

This is my go-to for quick exploratory data analysis. It’s much easier than creating individual patches when you have a standard X-Y relationship.

Bonus: Create Concentric Circles (Target Plots)

I’ve often had to create “target” plots for logistics or range-finding applications. The easiest way to do this is a simple loop with decreasing transparency.

import matplotlib.pyplot as plt

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

# US Logistics Range (e.g., Delivery Zones from a Chicago Hub)
radii = [10, 8, 6, 4, 2]
colors = ['#f8d7da', '#f1b0b7', '#e35d6a', '#d62027', '#a71d2a']
labels = ['Zone 5', 'Zone 4', 'Zone 3', 'Zone 2', 'Zone 1']

for r, c, l in zip(radii, colors, labels):
    circle = plt.Circle((0, 0), r, color=c, label=l)
    ax.add_patch(circle)

ax.set_xlim(-11, 11)
ax.set_ylim(-11, 11)
ax.set_aspect('equal')
plt.title("Logistics Delivery Zones (Chicago Hub)")
plt.legend(loc='upper right')
plt.show()

Notice how I plot the largest circle first? If you plot the small one first, the big one will just cover it up.

I hope this tutorial helped you understand the different ways to handle multiple circles in Matplotlib. Whether you need precision with patches or speed with scatter plots, you now have the tools to get it done.

You may read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.