Matplotlib Table as Y Axis
Created: 2023-10-16 Last Modified: 2025-02-22
When creating plots for evaluations the labels for an axis can get quite messy. This week I learned that in matplotlib you can, sort of, use a table as y-ticks. The code here is a modified version of this Stack Overflow question. There is also the official demo on the table. But I found it difficult to modify this demo to my needs.
from itertools import product
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.transforms import Bbox
n = 8 # number of data rows
# example setups I want to compare
table_data_text = [
["1st param", "2nd param"],
["SGD", "Adam"],
["linear", "relu"],
]
clust_data = np.random.random((10, n))
col_label = ["param", "optimizer", "activation"]
row_label = [f"setup {i}" for i in range(n)]
# generating all combinations here
table_data = list(product(*table_data_text))[:n]
barheight = 0.8
table_propotion = 0.5
margin = 0.10
plot_width = 10
# scale the image size with the number of element and give every row about 0.8 inch space, this can be adjusted to taste
plot_height = n * barheight
fig, ax = plt.subplots(figsize=(plot_width, plot_height))
# shift a little to the left to accomodate the table
# here we want the table to take up 40 percent of the left part
# you can add also bottom=margin to have a little space at the bottom
fig.subplots_adjust(left=table_propotion, top=1 - margin, bottom=margin)
ax = sns.boxplot(
data=clust_data,
width=barheight,
orient="h",
)
the_table = ax.table(
cellText=table_data,
rowLabels=row_label,
colLabels=col_label,
bbox=Bbox([[-1.0, 0.0], [0.0, 1 + 1 / n]]),
loc="center",
)
the_table.auto_set_font_size(False)
the_table.set_fontsize(9)
fig.canvas.draw() # need to draw the figure twice
plt.yticks([])
plt.savefig("plot.png")
This results into the following plot with a nice table on the side. This is by far easier to read instead of a construct label for each row like 1st param -- SGD -- linear
or so. Of course this can be further improved and adapted to specific needs. But for now this is a very good starting point. I could not find many resources on this topic and ChatGPT not able to produce any usable code.
To play around with the positioning of the table you need to modify the table_proportion
and the numbers in the Bbox
.
Further improvements
- You can adjust the table columns based on the text in the table
- Also adjust the plot width if necessary
- Maybe highlight a row because it stands out
Thank you for reading!