Matplotlib 3D散点图中如何通过三维坐标定位图例?
Great question! Unfortunately, Matplotlib does not support directly placing legends using 3D coordinates—here’s why, and how you can avoid manual trial-and-error for your plots:
Why loc=(0.5,0.5,0.5) doesn’t work
The loc parameter for ax.legend() only accepts either:
- A 2-element tuple (representing relative coordinates in the Axes’ 2D screen space, where
(0,0)is the bottom-left corner and(1,1)is the top-right), or - A preset string like
'upper right','center', etc.
3-element tuples (3D coordinates) are ignored by the legend system, since legends are inherently 2D elements tied to the Axes’ screen coordinate system, not the 3D plot space.
Solutions to avoid trial-and-error
1. Tie the legend to a specific 3D data point
If you want the legend to sit near a particular point in your 3D dataset, you can convert that point’s 3D coordinates to the Axes’ 2D relative coordinates. This way, the legend will stay aligned with that point even if you rotate the 3D view.
Here’s a working example:
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # Create sample 3D scatter plot fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # Sample data x1, y1, z1 = [1, 2, 3], [4, 5, 6], [7, 8, 9] x2, y2, z2 = [3, 2, 1], [6, 5, 4], [9, 8, 7] scatter1 = ax.scatter(x1, y1, z1, label='Dataset 1') scatter2 = ax.scatter(x2, y2, z2, label='Dataset 2') # Choose a 3D position where you want the legend to sit (e.g., the middle point of Dataset 1) target_3d_point = (2, 5, 8) # Convert 3D data coordinates to Axes' 2D relative coordinates screen_coords = ax.transData.transform(target_3d_point) axes_relative_coords = ax.transAxes.inverted().transform(screen_coords) # Add a small offset to avoid overlapping with the data point legend_x = axes_relative_coords[0] + 0.08 legend_y = axes_relative_coords[1] + 0.08 # Place the legend at the converted coordinates ax.legend(loc=(legend_x, legend_y), frameon=0) plt.show()
This code converts your target 3D point to the screen-based relative coordinates Matplotlib uses for legends, so you don’t have to guess values like (0.15, 0.65).
2. Use bbox_to_anchor for precise 2D positioning
If you don’t need to tie the legend to a data point, the bbox_to_anchor parameter gives you more control than just loc. For example, to place the legend’s center at 80% of the Axes’ width and height:
ax.legend(bbox_to_anchor=(0.8, 0.8), loc='center', frameon=0)
This is more intuitive than trial-and-error because you’re explicitly defining the legend’s anchor point in the Axes’ 2D space.
3. Stick to preset positions for consistency
If you want a consistent position across all plots (e.g., top-right corner), use one of Matplotlib’s preset loc strings:
ax.legend(loc='upper right', frameon=0)
Matplotlib will automatically place the legend in that 2D screen position, regardless of your 3D plot’s content.
内容的提问来源于stack exchange,提问作者Arraval

