October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk4 min

How to Add Text to Bar and Scatter Plots in Matplotlib

Use ax.bar_label() to put values on bar charts and ax.annotate() to attach text to scatter points, with working examples for formatting, stacked bars, offsets and arrows.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To label bars, pass the container returned by ax.bar() to ax.bar_label(). To label scatter points, loop over your coordinates and call ax.annotate() with a target xy and an offset xytext. Both take only a few lines. The choices that matter are how the numbers are formatted, where the text sits, and whether a note must stay attached to a data point.

Label bars with bar_label

ax.bar() returns a BarContainer, and ax.bar_label() places one text label per bar in that container. The Axes.bar reference recommends this helper for bar labels, and the bar_label reference documents the options below.

As an Amazon Associate I earn from qualifying purchases.

Basic value labels

The following example writes each value above its bar, rounded to one decimal place:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import matplotlib.pyplot as plt

categories = ["Apples", "Pears", "Plums"]
values = [12.5, 8.4, 15.0]

fig, ax = plt.subplots()
bars = ax.bar(categories, values)
ax.bar_label(bars, padding=3, fmt="{:.1f}")
plt.show()

padding is measured in points. bar_label returns a list of Annotation objects, so you can keep that return value if you need to restyle or remove individual labels later.

Formatting values

The fmt argument accepts three forms:

  • Percent-style strings, such as "%.1f", which work in every release.
  • Brace-style strings, such as "{:,.0f}" for thousands separators, which the reference lists as added in Matplotlib 3.7.
  • Callables that take a value and return a string, also added in Matplotlib 3.7.

If you need text that is not derived from the bar height, pass labels instead. Each entry is used as-is:

bars = ax.bar(categories, values)
ax.bar_label(bars, labels=[f"{v}%" for v in values], padding=3)

Stacked bars and label_type

The label_type argument decides which point of each segment is used:

  • label_type="edge" (the default) labels the segment endpoint. On a stacked bar, the number shown therefore reflects the position of that edge, not the segment’s own length.
  • label_type="center" reports the length of each segment, which is usually what you want when a stacked bar represents parts of a total.
import matplotlib.pyplot as plt

categories = ["Q1", "Q2", "Q3"]
part_a = [3, 2, 4]
part_b = [1, 5, 2]

fig, ax = plt.subplots()
bars_a = ax.bar(categories, part_a)
bars_b = ax.bar(categories, part_b, bottom=part_a)
ax.bar_label(bars_a, label_type="center")
ax.bar_label(bars_b, label_type="center")
plt.show()

Bar labels are aligned automatically. The helper does not accept horizontal or vertical alignment keywords, so if you need custom alignment, use annotate instead.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Labels that get clipped

Labels placed above the tallest bar can run past the top of the axes. Add headroom before you save the figure:

ax.set_ylim(0, max(values) * 1.15)

Then inspect the rendered figure, because the exact amount of space depends on your font size and figure dimensions. The bar_label reference notes that other styling keywords are passed through to annotate, so you can set properties such as fontsize in the same call.

Annotate scatter points

A scatter plot does not have a bar container, so each label must be placed individually. The Annotations guide describes annotate as text that explains, adds context to, or highlights part of a visualization. The core call is ax.annotate(text, xy=(x, y), ...), where xy is the point being labeled.

import matplotlib.pyplot as plt

x = [1, 2, 3, 4]
y = [2.5, 3.1, 1.8, 4.0]
names = ["A", "B", "C", "D"]

fig, ax = plt.subplots()
ax.scatter(x, y)
for xi, yi, name in zip(x, y, names):
    ax.annotate(name, xy=(xi, yi), xytext=(4, 4),
                textcoords="offset points")
plt.show()

Target and text positions

The point being labeled (xy) and the displayed text position (xytext) are separate coordinates. Setting textcoords="offset points" makes xytext a fixed offset from the point, measured in points. A label therefore stays next to its marker when you change the axis limits or resize the figure, because its offset does not depend on the data scale.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Adding an arrow

If the text sits far enough from its point that the link is unclear, add arrowprops:

ax.annotate(name, xy=(xi, yi), xytext=(30, 25),
            textcoords="offset points",
            arrowprops=dict(arrowstyle="->"))

Label only the points that matter. The API documents the placement mechanics, but how many labels a dense scatter plot can carry before it becomes hard to read is a design decision for you to make.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choosing between bar_label, annotate, and text

The three methods overlap, so the choice usually comes down to what the text belongs to.

Method Best used for Anchored to Arrow support Notable options
ax.bar_label(container) Values on bars returned by ax.bar() Each bar or stacked segment (label_type) Not described in the bar_label reference fmt, labels, padding, label_type
ax.annotate(text, xy=...) Labels tied to individual data points A data point xy, with text at xytext Yes, through arrowprops xytext, textcoords, arrowprops, text properties
ax.text(x, y, text) Free-standing words or notes at a fixed position The given x, y location, with no point relationship Not stated in the Text in Matplotlib guide Text properties such as fontsize

In practice, use bar_label whenever the labels come from bar heights, use annotate when a label must stay with a point or needs a pointer, and use text for a note at a known location. The Text in Matplotlib guide covers the text object itself. For how figures and Axes relate, including why fig, ax = plt.subplots() returns both, see the Introduction to Axes page and the matplotlib.axes API reference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Version notes

The current stable documentation is labeled version 3.11.2. Brace-style fmt strings and callables require Matplotlib 3.7 or later, so if an example fails with a formatting error, check your installed version:

python -c "import matplotlib; print(matplotlib.__version__)"

The stable reference also accepts a per-label array for padding, which is useful when some labels need more clearance than others. Use a single number on older installations.

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.