How to position a matplotlib patch outside of the axes range (so that it could be next to the title, or legend, or anywhere on the figure)

Viewed 1303

Given the following code:

fig, ax = plt.subplots()
ax.scatter([1, 2, 3, 4, 5], [34, 22, 11, 4, 6], s=100)
_ = ax.text(x=0, y=1.1, s="This is some text", transform=ax.transAxes, fontsize=20)

rect = mpl.patches.Rectangle(
    (0.5, 0.5), width=0.05, height=0.05, color="red", transform=ax.transAxes,
)
ax.add_patch(rect)

Which creates:

enter image description here

I would like to add the patch to the following location:

enter image description here

So that the plot looks as follows:

enter image description here

It seems that I am unable to have patches outside of the axes spines area though, for example the following code:

fig, ax = plt.subplots()
ax.scatter([1, 2, 3, 4, 5], [34, 22, 11, 4, 6], s=100)
_ = ax.text(x=0, y=1.1, s="This is some text", transform=ax.transAxes, fontsize=20)

rect = mpl.patches.Rectangle(
    (0.5, 0.5), width=0.05, height=0.5, color="red", transform=ax.transAxes,
)
ax.add_patch(rect)

gives

enter image description here

Looking in the method for matplotlib.figure.Figure I can't see anything for add_patch

['_clippath',
 '_path_effects',
 'get_clip_path',
 'get_path_effects',
 'get_transformed_clip_path_and_affine',
 'patch',
 'patches',
 'set_clip_path',
 'set_path_effects']

The above are the methods with pat in them.

2 Answers

You can disable clipping by setting clip_on=False, and then you can position the patch where you want. For example:

import matplotlib as mpl
from matplotlib import pyplot as plt

fig, ax = plt.subplots()
ax.scatter([1, 2, 3, 4, 5], [34, 22, 11, 4, 6], s=100)
_ = ax.text(x=0, y=1.1, s="This is some text", transform=ax.transAxes, fontsize=20)

rect = mpl.patches.Rectangle(
    (0.5, 1.1), width=0.05, height=0.05, color="red", transform=ax.transAxes,
    clip_on=False
)

ax.add_patch(rect)
plt.show()

Gives:

enter image description here

You can use chr(9607) to represent the patch:

print("This is some text", chr(9607)*3)

Output:

This is some text ▇▇▇

Into your code:

fig, ax = plt.subplots()
ax.scatter([1, 2, 3, 4, 5], [34, 22, 11, 4, 6], s=100)
_ = ax.text(x=0, y=1.1, s=f"This is some text {chr(9607)*3}", transform=ax.transAxes, fontsize=20)

rect = mpl.patches.Rectangle(
    (0.5, 0.5), width=0.05, height=0.05, color="red", transform=ax.transAxes,
)
ax.add_patch(rect)
Related