How to Plot Multiple Rectangles in Matplotlib

When I first started building custom data visualizations in Python, I often found myself needing to highlight specific regions on a chart. Whether it’s marking recession periods in economic data or outlining specific clusters in a scatter plot, knowing how to draw shapes is a fundamental skill.

In this tutorial, I will show you exactly how I plot multiple rectangles in Matplotlib using a few different professional approaches.

The Common Challenge with Multiple Shapes

Adding a single rectangle in Matplotlib is easy using patches.Rectangle. However, when you have a dataset with dozens of coordinates, adding them one by one becomes inefficient.

Over the years, I’ve found that the best method depends on whether your rectangles share the same styling or if they need to be treated as individual entities.

Below, I’ll walk you through the methods I use in my daily development work, utilizing examples relevant to US-based data analysis.

Method 1: Use a Loop with patches.Rectangle

This is the most intuitive method. I use this when I have a small number of rectangles (usually under 20), and I want to maintain individual control over each one.

In this example, let’s visualize different “Zoning Districts” in a hypothetical US city block layout.

import matplotlib.pyplot as plt
import matplotlib.patches as patches

def plot_zoning_districts():
    # Create a figure and axis
    fig, ax = plt.subplots(figsize=(10, 8))

    # Real-world US Context: Mapping out property lots in a development
    # Format: [x, y, width, height, label, color]
    lots = [
        [1, 1, 2, 3, 'Residential A', '#ff9999'],
        [4, 1, 2, 3, 'Residential B', '#66b3ff'],
        [7, 1, 3, 5, 'Commercial Zone', '#99ff99'],
        [1, 5, 5, 2, 'Public Park', '#ffcc99'],
    ]

    for lot in lots:
        x, y, w, h, label, color = lot
        
        # Creating the rectangle object
        rect = patches.Rectangle((x, y), w, h, linewidth=2, 
                                 edgecolor='black', facecolor=color, alpha=0.7)
        
        # Adding the patch to the axes
        ax.add_patch(rect)
        
        # Adding a text label in the center of the rectangle
        ax.text(x + w/2, y + h/2, label, ha='center', va='center', weight='bold')

    # Setting plot limits based on our "city block"
    ax.set_xlim(0, 12)
    ax.set_ylim(0, 10)
    ax.set_aspect('equal')
    
    plt.title('Urban Planning Map: Downtown District Layout', fontsize=14)
    plt.xlabel('West-East Street Grid (Blocks)')
    plt.ylabel('North-South Street Grid (Blocks)')
    plt.grid(linestyle='--', alpha=0.5)
    
    plt.show()

plot_zoning_districts()

You can refer to the screenshot below to see the output.

Plot Multiple Rectangles in Matplotlib

I prefer this when labels are necessary. By looping, I can easily calculate the center point of each rectangle to place descriptive text, which is a common requirement in architectural or logistical plotting.

Method 2: Use PatchCollection for High Performance

When I’m dealing with hundreds of rectangles, such as visualizing thousands of sensor placements or a dense heat map, looping becomes slow.

The PatchCollection class is built for speed. It allows Matplotlib to render all shapes in a single draw call. Here, we will simulate analyzing the US Treasury Yield curve segments or “Risk Buckets.”

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

def plot_financial_risk_buckets():
    fig, ax = plt.subplots(figsize=(12, 6))

    # Generating a larger number of rectangles (e.g., US Market Data Segments)
    rects = []
    
    # Let's create a grid representing different market sectors
    for i in range(10):
        for j in range(5):
            # x, y coordinates and width/height
            # Representing "Volatility" vs "Return" segments
            rect = patches.Rectangle((i*1.1, j*1.1), 1, 1)
            rects.append(rect)

    # Create the collection
    # We can pass a colormap to color the rectangles based on data
    pc = PatchCollection(rects, cmap='RdYlGn', edgecolors='black', alpha=0.8)
    
    # Simulating "Performance Data" for each rectangle (0 to 100)
    performance_data = np.random.randint(0, 100, len(rects))
    pc.set_array(performance_data)

    # Add the collection to the plot
    ax.add_collection(pc)

    # Styling the plot
    ax.set_xlim(-1, 12)
    ax.set_ylim(-1, 7)
    
    # Adding a colorbar to show performance
    cbar = fig.colorbar(pc, ax=ax)
    cbar.set_label('Portfolio Performance Index (%)')

    plt.title('US Equities Market Sector Analysis (Heatmap Grid)', fontsize=15)
    plt.xlabel('Sector Risk Profile')
    plt.ylabel('Market Capitalization Tier')
    
    plt.tight_layout()
    plt.show()

plot_financial_risk_buckets()

You can refer to the screenshot below to see the output.

How to Plot Multiple Rectangles in Matplotlib

Notice I didn’t set colors in the loop. By using pc.set_array(), I can map a list of values to a colormap. This is the professional way to handle large-scale data visualization in Matplotlib.

Method 3: Highlight Time-Series Data (Recession Shading)

In the US financial industry, a very common task is shading multiple “recession periods” on a stock price chart.

While you could use axvspan, using Rectangle gives you more control if the “shading” needs to have specific heights or borders.

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import pandas as pd

def plot_us_economic_recessions():
    # Simulated S&P 500 Style Growth Data
    years = list(range(1990, 2025))
    values = [100 + (i*5) + (10 if i > 15 else 0) for i in range(len(years))]

    fig, ax = plt.subplots(figsize=(12, 6))
    ax.plot(years, values, color='navy', linewidth=2, label='Economic Index')

    # Define US Recession periods (Approximate dates)
    # (Start Year, Duration in Years)
    recessions = [
        (1990, 1),
        (2001, 0.8),
        (2008, 1.5),
        (2020, 0.5)
    ]

    for start, duration in recessions:
        # Drawing a rectangle that covers the full height of the plot
        # Rectangle((x, y), width, height)
        rect = patches.Rectangle((start, 0), duration, 300, 
                                 linewidth=0, facecolor='red', alpha=0.2)
        ax.add_patch(rect)

    ax.set_ylim(80, 280)
    plt.title('Historical Performance of US Markets with Recession Overlays', fontsize=14)
    plt.xlabel('Year')
    plt.ylabel('Index Value (USD)')
    plt.legend()
    
    plt.show()

plot_us_economic_recessions()

You can refer to the screenshot below to see the output.

Matplotlib Plot Multiple Rectangles

Key Customization Options

When you are plotting these shapes, there are four parameters I always tweak to make the plot look professional:

  1. alpha: Never leave it at 1.0 if shapes overlap. Setting it to 0.5 or 0.7 makes the grid lines visible behind the shapes.
  2. joinstyle: If you have thick borders, use joinstyle=’round’ or ‘miter’ to control how corners look.
  3. zorder: If your rectangles are hiding your data points, set zorder=1 for rectangles and zorder=2 for your lines/scatters.
  4. hatch: In US government reports, we often use patterns (like ‘///’ or ‘…’) for accessibility in black-and-white printing. You can add hatch=’///’ to any Rectangle object.

You may also 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.