Matplotlib Table: Add, Style, and Format Table Cells

Quick answer: Create a Matplotlib table with ax.table(), format the displayed strings before passing them as cellText, and keep enough figure space for labels and cells. Style only the cells that convey meaning so the table remains readable in saved output.

Python Pool infographic showing Matplotlib table data labels cell styling widths and layout
A Matplotlib table is most useful when the data, labels, cell widths, typography, and surrounding figure layout are designed together.

A Matplotlib table is useful when a figure needs a compact numeric summary next to a chart. The table is drawn as part of the figure, so it can be shown with plt.show(), exported with the plot, and styled with the same figure workflow you use for axes, labels, and annotations.

Use matplotlib.pyplot.table() or Axes.table() for small summaries: model scores, monthly totals, confusion-matrix style values, report snippets, or a few rows of chart data. For large datasets, a spreadsheet or DataFrame export is usually a better fit; see the Python Pool guides on Pandas to_csv() and openpyxl when the table itself is the main output.

Basic Matplotlib table example

The easiest pattern is to create a normal figure and axes, hide the axes, and place the table at the center. cellText supplies the rows, while colLabels supplies the header row.

import matplotlib.pyplot as plt

data = [
    ["Jan", 120, 75, 45],
    ["Feb", 150, 92, 58],
    ["Mar", 175, 110, 65],
    ["Apr", 168, 101, 67],
]
columns = ["Month", "Sales", "Cost", "Profit"]

fig, ax = plt.subplots(figsize=(7, 3))
ax.axis("off")

table = ax.table(
    cellText=data,
    colLabels=columns,
    loc="center",
    cellLoc="center",
)

table.auto_set_font_size(False)
table.set_fontsize(11)
table.scale(1, 1.4)

plt.show()

The same idea works with plt.table(), but the axes method is easier to control once the figure also contains charts. Matplotlib documents both the pyplot table function and the Axes.table method.

Important table parameters

These options handle most table layouts:

  • cellText: a two-dimensional list of row values.
  • colLabels: labels for the header row.
  • rowLabels: labels shown at the left of each row.
  • cellLoc: text alignment inside cells, such as "center", "left", or "right".
  • loc: where the table sits inside the axes, such as "center", "bottom", or "upper right".
  • colWidths: relative widths for columns when the automatic size is not enough.

Row labels are helpful when each row represents an entity and the columns are metrics:

import matplotlib.pyplot as plt

scores = [
    [98, 94, 91],
    [88, 90, 86],
]

fig, ax = plt.subplots(figsize=(6, 2.5))
ax.axis("off")

ax.table(
    cellText=scores,
    rowLabels=["Model A", "Model B"],
    colLabels=["Precision", "Recall", "F1"],
    loc="center",
    cellLoc="center",
)

plt.show()

Python Pool infographic showing rows, columns, headers, cells, and a Matplotlib table
Table data: Rows, columns, headers, cells, and a Matplotlib table.

Style headers, cells, and text

The object returned by table() is a Matplotlib Table. You can loop through its cells and apply colors, borders, font weight, and conditional formatting. The header row uses row index 0 when column labels are present.

for (row, col), cell in table.get_celld().items():
    cell.set_edgecolor("#d0d7de")

    if row == 0:
        cell.set_facecolor("#1f77b4")
        cell.set_text_props(color="white", weight="bold")
    elif col == 3:
        cell.set_facecolor("#e6ffed")
    elif row % 2 == 0:
        cell.set_facecolor("#f6f8fa")

Use styling sparingly. A table inside a plot has limited space, so one header color, light borders, and a single highlight column usually reads better than many colors. If the figure also has annotations, the Matplotlib text guide covers label placement and text styling in more detail.

Resize a Matplotlib table

Tables often look too small or too compressed on the first attempt. Disable automatic font sizing, choose a fixed font size, and then scale the table vertically. If the table is placed under a plot, figure size and subplot spacing matter as much as the table settings.

table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.1, 1.5)

fig.tight_layout()

When a figure has multiple axes, create it with plt.subplots() and tune spacing intentionally. The official docs for pyplot.subplots and Python Pool’s guide to Matplotlib subplot spacing are useful when the table crowds the chart.

Python Pool infographic mapping table cells through colors, widths, alignment, font size, and edges
Cell styling: Table cells through colors, widths, alignment, font size, and edges.

Add a table below a chart

A practical layout is a chart on the top axes and a table on the bottom axes. This keeps the visual trend and exact values together without forcing labels onto every bar or point.

import matplotlib.pyplot as plt

months = ["Jan", "Feb", "Mar", "Apr"]
sales = [120, 150, 175, 168]
profit = [45, 58, 65, 67]
summary = [[month, sale, margin] for month, sale, margin in zip(months, sales, profit)]

fig, (ax_bar, ax_table) = plt.subplots(
    nrows=2,
    figsize=(7, 5),
    gridspec_kw={"height_ratios": [3, 1]},
)

ax_bar.bar(months, profit, color="#f97316")
ax_bar.set_title("Monthly profit")
ax_bar.set_ylabel("Profit")

ax_table.axis("off")
ax_table.table(
    cellText=summary,
    colLabels=["Month", "Sales", "Profit"],
    loc="center",
    cellLoc="center",
)

fig.tight_layout()
plt.show()

Hiding the table axes with axis("off") removes ticks and spines. The Matplotlib docs for Axes.axis explain the axis visibility controls behind that line.

Export the table figure

Because the table is part of the Matplotlib figure, exporting is the same as exporting any other plot. Use bbox_inches="tight" when the table sits near the edge of the canvas.

fig.savefig("sales-table.png", dpi=160, bbox_inches="tight")
fig.savefig("sales-table.pdf", bbox_inches="tight")

For more export options, use the official savefig documentation or the Python Pool guide to Matplotlib savefig(). The official Matplotlib table demo is also a good reference for combining bars and tables.

Common problems and fixes

The table overlaps the chart. Put the table on a separate axes, increase figure height, or adjust subplot spacing. Avoid squeezing a full report table under a small plot.

Text is cut off. Increase figsize, reduce font size, set colWidths, or export with bbox_inches="tight".

The table has too many rows. Summarize the data first. Matplotlib tables are for presentation, not browsing hundreds of records.

Numbers need formatting. Format values before passing them to cellText. For example, use f-strings to add percentages, currency symbols, or fixed decimals.

rows = [
    ["Jan", f"${120_000:,.0f}", f"{45 / 120:.1%}"],
    ["Feb", f"${150_000:,.0f}", f"{58 / 150:.1%}"],
]

For numerical matrix workflows, table output can summarize intermediate values, but calculations should stay in NumPy or plain Python first. The guide on Gaussian elimination in Python shows a matrix-focused example where clear tabular output can help explain the steps.

Python Pool infographic comparing axes coordinates, bbox, scale, row height, and figure space
Table layout: Axes coordinates, bbox, scale, row height, and figure space.

Conclusion

Use a Matplotlib table when a figure needs a small, readable data summary. Start with ax.table(cellText=..., colLabels=...), hide unused axes, then tune font size, cell scaling, and spacing. For production figures, keep the table compact and export with savefig() so the chart and table remain together.

Create A Basic Table

ax.table() accepts a rectangular cellText sequence plus optional row and column labels. Start with strings that already have the desired precision and units instead of relying on a table to format arbitrary objects.

import matplotlib.pyplot as plt

rows = [["Ada", "98"], ["Grace", "95"]]
fig, ax = plt.subplots(figsize=(5, 2.5))
ax.axis("off")
ax.table(cellText=rows, colLabels=["name", "score"], loc="center")
plt.show()

Format Values And Widths

Format numeric values before building the table, then use colWidths when long labels need predictable space. A table that fits in a notebook can still clip when saved at a different DPI or aspect ratio.

import matplotlib.pyplot as plt

values = [("A", 0.9234), ("B", 0.8712)]
rows = [[name, f"{score:.1%}"] for name, score in values]
fig, ax = plt.subplots(figsize=(5, 2.5))
ax.axis("off")
ax.table(cellText=rows, colLabels=["group", "accuracy"], colWidths=[0.4, 0.3], loc="center")
plt.show()
Python Pool infographic testing long text, missing values, headers, export size, and readability
Table checks: Long text, missing values, headers, export size, and readability.

Style Cells By Meaning

The Table object exposes cells by row and column coordinate. Use a restrained facecolor, text color, and edge style for headers or warning rows, and keep contrast high enough for small screens and printed output.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(5, 2.5))
ax.axis("off")
table = ax.table(cellText=[["ready", "200"], ["failed", "500"]], colLabels=["state", "count"], loc="center")
for cell in table.get_celld().values():
    cell.set_edgecolor("#d0d7de")
table[(0, 0)].set_facecolor("#e8f1fb")
plt.show()

Protect The Layout

Reserve room around the table with constrained_layout, tight_layout, or explicit margins. Inspect the final PNG or PDF because table cells, tick labels, and a title can overlap even when the axes itself has no overflow.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(6, 3), constrained_layout=True)
ax.axis("off")
ax.set_title("Evaluation summary")
ax.table(cellText=[["precision", "0.91"], ["recall", "0.88"]], colLabels=["metric", "value"], loc="center")
fig.savefig("summary.png", dpi=160)
plt.close(fig)

The official Matplotlib table() reference documents cell text, labels, widths, and the returned Table object. Pair the table with figure sizing when the output format changes.

For related figure layout work, compare Matplotlib text, figure sizing, and tight layout when a table must fit both interactive and saved output.

Frequently Asked Questions

How do I add a table to a Matplotlib plot?

Call ax.table() with cellText and optional rowLabels and colLabels, then adjust its scale and the figure layout.

How do I change Matplotlib table cell colors?

Use the returned table cells and set each cell’s facecolor, text color, or edge color according to the meaning of the row or column.

Why is my Matplotlib table cut off?

Reserve figure space with tight_layout(), constrained_layout, or explicit margins and verify the saved output rather than only the interactive window.

Can I format numbers in a Matplotlib table?

Format the strings before passing them as cellText so precision, units, and missing values are controlled explicitly.

Subscribe
Notify of
guest
3 Comments
Oldest
Newest Most Voted
Jet
Jet
5 years ago

I do lots of programming in several programming languages. I have taken 3 courses in Python and I tutor programming. This webpage had helpful info and ideas for some graphics I’m creating.

Pratik Kinage
Admin
5 years ago
Reply to  Jet

Thank you for your encouraging words.

Regards,
Pratik

efueyo
efueyo
4 years ago

Dear all. How can we modify the height of the cells in each row? Regards