2025, Nov 03 21:00

How to Center a Pie Chart on an Exact Data Point in Matplotlib with inset_axes and transData

Center a Matplotlib pie chart on an exact data point using inset_axes with transData. Includes code and data-coordinate placement to avoid transform pitfalls.

Pinning a pie chart to an exact data point in a Matplotlib plot sounds trivial until the axes transform gets in the way. If you place a new axes via normalized figure coordinates, the pie will center on that new axes, not on the original (x, y) in data space. The fix is to position the inset using data coordinates so the pie aligns with the point you care about.

Problem setup

The goal: draw a line plot, mark a specific point, create a small axes, and render a pie chart so that it is centered exactly at that point. Here’s a minimal setup showing why a naive approach doesn’t center the pie on the point:

import matplotlib.pyplot as plt
import numpy as np
canvas, base_ax = plt.subplots(nrows=1, ncols=1, figsize=(6, 3))
base_ax.set_xlim(0, 16)
base_ax.set_ylim(8, 12)
# Plot a sine wave
xs = np.arange(0, 5 * np.pi, 0.1)
ys = np.sin(xs) + 10
base_ax.plot(xs, ys, color="blue")
# Mark the target data point at x=12, y=10
base_ax.plot(12, 10, marker="o", color="red")
# Normalize the target coordinates to [0, 1]
u_norm = (12 - 0) / (16 - 0)  # 0.75
v_norm = (10 - 8) / (12 - 8)   # 0.5
# Place a small axes via figure-normalized rectangle
p_left = 0.75
p_bottom = 0.5
box_w = 0.1
box_h = 0.1
mini_ax = canvas.add_axes(rect=(p_left, p_bottom, box_w, box_h))
# Draw the pie
mini_ax.pie((0.2, 0.3, 0.5))

Why this doesn’t center the pie on the point

The rectangle passed to the new axes is specified in a normalized 0–1 coordinate system. The pie is then centered on that small axes, i.e., at the midpoint of the rectangle. While the values for the left and bottom were computed from data limits and normalized, the axes itself is not anchored in data coordinates. The result is a pie centered in the tiny inset area, not guaranteed to be centered on the original (12, 10) in data space.

The robust approach: place the inset in data coordinates

To center the pie on a data point, the new axes should be positioned in data coordinates. Using Axes.inset_axes with transform=ax.transData allows the rectangle to be interpreted in data units. Subtract half of the desired width and height around the point so the inset is centered on it, then draw the pie.

import matplotlib.pyplot as plt
import numpy as np
scene, host_ax = plt.subplots(nrows=1, ncols=1, figsize=(6, 3))
host_ax.set_xlim(0, 16)
host_ax.set_ylim(8, 12)
# Plot a sine wave
xv = np.arange(0, 5 * np.pi, 0.1)
yv = np.sin(xv) + 10
host_ax.plot(xv, yv, color="blue")
# The data point where the pie should be centered
center_pt = (12, 10)
host_ax.plot(*center_pt, marker="o", color="red")
# Width and height of the inset in data units
span_x = 2
span_y = 0.5
# Center the inset rectangle on the data point
rect_data = [center_pt[0] - span_x / 2, center_pt[1] - span_y / 2, span_x, span_y]
# Create the inset in data coordinates and draw the pie
child_ax = host_ax.inset_axes(rect_data, transform=host_ax.transData)
child_ax.pie((0.2, 0.3, 0.5))

What’s happening under the hood

By passing transform=ax.transData to inset_axes, the rectangle is interpreted directly in the axes’ data coordinate system. The subtraction of half of the width and height makes the rectangle’s center coincide with the target point, so the pie chart is visually centered exactly where intended.

Why this matters

When you need to annotate a precise position in your plot with a pie chart, using data coordinates avoids the mismatch between normalized rectangles and actual data positions. It also avoids the overhead of constructing wedges by hand; using the built-in pie method is simpler than manually defining pie slices. There is also a gallery example of scatter-style pie charts that explores a related idea.

Takeaways

If you want a pie chart centered on a specific data point, create the inset with Axes.inset_axes, supply a rectangle in data units, and offset by half the inset’s dimensions around the point. That keeps the visual intent aligned with the data and reduces boilerplate.

The article is based on a question from StackOverflow by Bera and an answer by Matt Pitkin.