Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions doc/api/next_api_changes/deprecations/29152_REC.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
``pie`` *labels* and *labeldistance* parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Currently the *labels* parameter of `~.Axes.pie` is used both for annotating the
pie wedges directly, and for automatic legend entries. For consistency
with other plotting methods, in future *labels* will only be used for the legend.

The *labeldistance* parameter will therefore default to ``None`` from Matplotlib
3.14, when it will also be deprecated and then removed in Matplotlib 3.16. To
preserve the existing behavior for now, set ``labeldistance=1.1``. For the longer
term, to place labels on the wedges use the new *wedge_labels* and
*wedge_label_distance* parameters of `~.Axes.pie` or the `~.Axes.pie_label` method.
Note that `~.Axes.pie_label` allows for more customization of the label positions via
the *rotate* and *alignment* parameters as well as *distance*.
26 changes: 26 additions & 0 deletions doc/release/next_whats_new/pie_wedge_labels.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
New *wedge_labels* parameter for pie
------------------------------------

`~.Axes.pie` now accepts a *wedge_labels* parameter as a shortcut to the
`~.Axes.pie_label` method. This may be used for simple annotation of the wedges
of the pie chart. It can take

* a list of strings, similar to the existing *labels* parameter
* a format string similar to the existing *autopct* parameter, except that it
uses the `str.format` method and it can handle absolute values as well as
fractions/percentages
Comment on lines +6 to +11
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
of the pie chart. It can take
* a list of strings, similar to the existing *labels* parameter
* a format string similar to the existing *autopct* parameter except that it
uses the `str.format` method, and it can handle absolute values as well as
fractions/percentages
of the pie chart. It can take
* a list of strings, similar to the existing *labels* parameter
* a format string similar to the existing *autopct* parameter, except that it
uses the `str.format` method and it can handle absolute values as well as
fractions/percentages


*wedge_labels* has an accompanying *wedge_label_distance* parameter, to control
the distance of the labels from the center of the pie.


.. plot::
:include-source: true
:alt: Two pie charts. The chart on the left has labels 'foo' and 'bar' outside the wedges. The chart on the right has labels '1' and '2' inside the wedges.

import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(ncols=2, layout='constrained')

ax1.pie([1, 2], wedge_labels=['foo', 'bar'], wedge_label_distance=1.1)
ax2.pie([1, 2], wedge_labels='{absval:d}', wedge_label_distance=0.6)
6 changes: 3 additions & 3 deletions galleries/examples/misc/svg_filter_pie.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@

# We want to draw the shadow for each pie, but we will not use "shadow"
# option as it doesn't save the references to the shadow patches.
pie = ax.pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%')
pie = ax.pie(fracs, explode=explode, wedge_labels=labels, wedge_label_distance=1.1)

for w in pie.wedges:
for w, label in zip(pie.wedges, labels):
# set the id with the label.
w.set_gid(w.get_label())
w.set_gid(label)

# we don't want to draw the edge of the pie
w.set_edgecolor("none")
Expand Down
7 changes: 5 additions & 2 deletions galleries/examples/pie_and_polar_charts/bar_of_pie.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
explode = [0.1, 0, 0]
# rotate so that first wedge is split by the x-axis
angle = -180 * overall_ratios[0]
pie = ax1.pie(overall_ratios, autopct='%1.1f%%', startangle=angle,
labels=labels, explode=explode)
pie = ax1.pie(overall_ratios, startangle=angle, explode=explode)

# label the wedges with our label strings and the ratios as percentages
ax1.pie_label(pie, labels, distance=1.1)
ax1.pie_label(pie, '{frac:.1%}', distance=0.6)

# bar chart parameters
age_ratios = [.33, .54, .07, .06]
Expand Down
70 changes: 41 additions & 29 deletions galleries/examples/pie_and_polar_charts/pie_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,68 @@
# ------------
#
# Plot a pie chart of animals and label the slices. To add
# labels, pass a list of labels to the *labels* parameter
# labels, pass a list of labels to the *wedge_labels* parameter.

import matplotlib.pyplot as plt

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
sizes = [12, 24, 36, 8]

fig, ax = plt.subplots()
ax.pie(sizes, labels=labels)
ax.pie(sizes, wedge_labels=labels)

# %%
# Each slice of the pie chart is a `.patches.Wedge` object; therefore in
# addition to the customizations shown here, each wedge can be customized using
# the *wedgeprops* argument, as demonstrated in
# :doc:`/gallery/pie_and_polar_charts/nested_pie`.
#
# Set label positions
# -------------------
# If you want the labels outside the pie, set a *wedge_label_distance* greater than 1.
# This is the distance from the center of the pie as a fraction of its radius.

fig, ax = plt.subplots()
ax.pie(sizes, wedge_labels=labels, wedge_label_distance=1.1)

# %%
#
# Auto-label slices
# -----------------
#
# Pass a function or format string to *autopct* to label slices.
# Pass a format string to *wedge_labels* to label slices with their values...

fig, ax = plt.subplots()
ax.pie(sizes, wedge_labels='{absval:.1f}')

# %%
#
# ...or with their percentages...

fig, ax = plt.subplots()
ax.pie(sizes, wedge_labels='{frac:.1%}')

# %%
#
# ...or both.

fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%1.1f%%')
ax.pie(sizes, wedge_labels='{absval:d}\n{frac:.1%}')

# %%
#
# For more control over labels, or to add multiple sets, see
# :doc:`/gallery/pie_and_polar_charts/pie_label`.

# %%
# By default, the label values are obtained from the percent size of the slice.
#
# Color slices
# ------------
#
# Pass a list of colors to *colors* to set the color of each slice.

fig, ax = plt.subplots()
ax.pie(sizes, labels=labels,
colors=['olivedrab', 'rosybrown', 'gray', 'saddlebrown'])
ax.pie(sizes, colors=['olivedrab', 'rosybrown', 'gray', 'saddlebrown'])

# %%
# Hatch slices
Expand All @@ -58,22 +85,9 @@
# Pass a list of hatch patterns to *hatch* to set the pattern of each slice.

fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, hatch=['**O', 'oO', 'O.O', '.||.'])

# %%
# Swap label and autopct text positions
# -------------------------------------
# Use the *labeldistance* and *pctdistance* parameters to position the *labels*
# and *autopct* text respectively.

fig, ax = plt.subplots()
ax.pie(sizes, labels=labels, autopct='%1.1f%%',
pctdistance=1.25, labeldistance=.6)
ax.pie(sizes, hatch=['**O', 'oO', 'O.O', '.||.'])

# %%
# *labeldistance* and *pctdistance* are ratios of the radius; therefore they
# vary between ``0`` for the center of the pie and ``1`` for the edge of the
# pie, and can be set to greater than ``1`` to place text outside the pie.
#
# Explode, shade, and rotate slices
# ---------------------------------
Expand All @@ -86,11 +100,10 @@
#
# This example orders the slices, separates (explodes) them, and rotates them.

explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
explode = (0, 0.2, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')

fig, ax = plt.subplots()
ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90)
ax.pie(sizes, explode=explode, wedge_labels='{frac:.1%}', shadow=True, startangle=90)
plt.show()

# %%
Expand All @@ -107,8 +120,7 @@

fig, ax = plt.subplots()

ax.pie(sizes, labels=labels, autopct='%.0f%%',
textprops={'size': 'small'}, radius=0.5)
ax.pie(sizes, wedge_labels='{frac:.1%}', textprops={'size': 'small'}, radius=0.5)
plt.show()

# %%
Expand All @@ -119,8 +131,8 @@
# the `.Shadow` patch. This can be used to modify the default shadow.

fig, ax = plt.subplots()
ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
shadow={'ox': -0.04, 'edgecolor': 'none', 'shade': 0.9}, startangle=90)
ax.pie(sizes, explode=explode, shadow={'ox': -0.04, 'edgecolor': 'none', 'shade': 0.9},
startangle=90)
plt.show()

# %%
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/_api/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ from .deprecation import ( # noqa: F401, re-exported API
_T = TypeVar("_T")

class _Unset: ...
UNSET = _Unset()
Copy link
Copy Markdown
Member Author

@rcomer rcomer Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this, mypy complains _UNSET doesn't exist when checking pyplot.py.


class classproperty(Any):
def __init__(
Expand Down
85 changes: 75 additions & 10 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
BarContainer, ErrorbarContainer, PieContainer, StemContainer)
from matplotlib.text import Text
from matplotlib.transforms import _ScaledRotation
from matplotlib._api import UNSET as _UNSET

_log = logging.getLogger(__name__)

Expand Down Expand Up @@ -3534,13 +3535,13 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
self.add_container(stem_container)
return stem_container

@_api.make_keyword_only("3.10", "explode")
@_preprocess_data(replace_names=["x", "explode", "labels", "colors"])
def pie(self, x, explode=None, labels=None, colors=None,
autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
startangle=0, radius=1, counterclock=True,
wedgeprops=None, textprops=None, center=(0, 0),
frame=False, rotatelabels=False, *, normalize=True, hatch=None):
@_preprocess_data(replace_names=["x", "explode", "labels", "colors",
"wedge_labels"])
def pie(self, x, *, explode=None, labels=None, colors=None, wedge_labels=None,
wedge_label_distance=0.6, autopct=None, pctdistance=0.6, shadow=False,
labeldistance=_UNSET, startangle=0, radius=1, counterclock=True,
wedgeprops=None, textprops=None, center=(0, 0), frame=False,
rotatelabels=False, normalize=True, hatch=None):
"""
Plot a pie chart.

Expand All @@ -3560,7 +3561,13 @@ def pie(self, x, explode=None, labels=None, colors=None,
of the radius with which to offset each wedge.

labels : list, default: None
A sequence of strings providing the labels for each wedge
A sequence of strings providing the legend labels for each wedge.

.. deprecated:: 3.12
In future these labels will not appear on the wedges but only
be made available for the legend (see *labeldistance* below).
To place labels on the wedges, use *wedge_labels* or the
`pie_label` method.

colors : :mpltype:`color` or list of :mpltype:`color`, default: None
A sequence of colors through which the pie chart will cycle. If
Expand All @@ -3573,12 +3580,35 @@ def pie(self, x, explode=None, labels=None, colors=None,

.. versionadded:: 3.7

wedge_labels : str or list of str, optional
A sequence of strings providing the labels for each wedge, or a format
string with ``absval`` and/or ``frac`` placeholders. For example, to label
each wedge with its value and the percentage in brackets::

wedge_labels="{absval:d} ({frac:.0%})"

For more control or to add multiple sets of labels, use `pie_label`
instead.

.. versionadded:: 3.12

wedge_label_distance : float, default: 0.6
The radial position of the wedge labels, relative to the pie radius.
Values > 1 are outside the wedge and values < 1 are inside the wedge.

.. versionadded:: 3.12

autopct : None or str or callable, default: None
If not *None*, *autopct* is a string or function used to label the
wedges with their numeric value. The label will be placed inside
the wedge. If *autopct* is a format string, the label will be
``fmt % pct``. If *autopct* is a function, then it will be called.

.. admonition:: Discouraged

Consider using the *wedge_labels* parameter or `pie_label`
method instead.

pctdistance : float, default: 0.6
The relative distance along the radius at which the text
generated by *autopct* is drawn. To draw the text outside the pie,
Expand All @@ -3591,6 +3621,11 @@ def pie(self, x, explode=None, labels=None, colors=None,
If set to ``None``, labels are not drawn but are still stored for
use in `.legend`.

.. deprecated:: 3.12
From v3.14 *labeldistance* will default to ``None`` and will
later be removed altogether. Use *wedge_labels* and
*wedge_label_distance* or the `pie_label` method instead.

shadow : bool or dict, default: False
If bool, whether to draw a shadow beneath the pie. If dict, draw a shadow
passing the properties in the dict to `.Shadow`.
Expand Down Expand Up @@ -3672,8 +3707,33 @@ def pie(self, x, explode=None, labels=None, colors=None,
raise ValueError('Cannot plot an unnormalized pie with sum(x) > 1')
else:
fracs = x

if labeldistance is _UNSET:
# NB: when the labeldistance default changes, both labeldistance and
# rotatelabels should be deprecated for removal.
if labels is not None:
msg = (
"From %(removal)s labeldistance will default to None, so that the "
"strings provided in the labels parameter are only available for "
"the legend. Later labeldistance will be removed completely. To "
"preserve existing behavior for now, pass labeldistance=1.1. "
"Consider using the wedge_labels parameter or the pie_label method "
"instead of the labels parameter."
)
_api.warn_deprecated("3.12", message=msg)
labeldistance = 1.1

if labels is None:
labels = [''] * len(x)
else:
if wedge_labels is not None and labeldistance is not None:
raise ValueError(
'wedge_labels is a replacement for labels when annotating the '
'wedges, so the two should not be used together unless '
'labeldistance is None. To add multiple sets of labels, use the '
'pie_label method.'
)

if explode is None:
explode = [0] * len(x)
if len(x) != len(labels):
Expand Down Expand Up @@ -3731,11 +3791,16 @@ def get_next_color():

pc = PieContainer(slices, x, normalize)

if labeldistance is None:
if wedge_labels is not None:
self.pie_label(pc, wedge_labels, distance=wedge_label_distance,
textprops=textprops)

elif labeldistance is None:
# Insert an empty list of texts for backwards compatibility of the
# return value.
pc.add_texts([])
else:

if labeldistance is not None:
Comment thread
timhoffm marked this conversation as resolved.
# Add labels to the wedges.
labels_textprops = {
'fontsize': mpl.rcParams['xtick.labelsize'],
Expand Down
5 changes: 4 additions & 1 deletion lib/matplotlib/axes/_axes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import matplotlib.tri as mtri
import matplotlib.table as mtable
import matplotlib.stackplot as mstack
import matplotlib.streamplot as mstream
from matplotlib._api import _Unset

import PIL.Image
from collections.abc import Callable, Iterable, Sequence
Expand Down Expand Up @@ -310,10 +311,12 @@ class Axes(_AxesBase):
explode: ArrayLike | None = ...,
labels: Sequence[str] | None = ...,
colors: ColorType | Sequence[ColorType] | None = ...,
wedge_labels: str | Sequence | None = ...,
wedge_label_distance: float | Sequence = ...,
autopct: str | Callable[[float], str] | None = ...,
pctdistance: float = ...,
shadow: bool = ...,
labeldistance: float | None = ...,
labeldistance: float | None | _Unset = ...,
startangle: float = ...,
radius: float = ...,
counterclock: bool = ...,
Expand Down
Loading
Loading