automatically position text box in matplotlib

Question:

Is there a way of telling pyplot.text() a location like you can with pyplot.legend()?

Something like the legend argument would be excellent:

plt.legend(loc="upper left")

I am trying to label subplots with different axes using letters (e.g. “A”,”B”). I figure there’s got to be a better way than manually estimating the position.

Thanks

Asked By: Anake

||

Answers:

Just use annotate and specify axis coordinates. For example, “upper left” would be:

plt.annotate('Something', xy=(0.05, 0.95), xycoords='axes fraction')

You could also get fancier and specify a constant offset in points:

plt.annotate('Something', xy=(0, 1), xytext=(12, -12), va='top'
             xycoords='axes fraction', textcoords='offset points')

For more explanation see the examples here and the more detailed examples here.

Answered By: Joe Kington

I’m not sure if this was available when I originally posted the question but using the loc parameter can now actually be used. Below is an example:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText

# make some data
x = np.arange(10)
y = x

# set up figure and axes
f, ax = plt.subplots(1,1)

# loc works the same as it does with figures (though best doesn't work)
# pad=5 will increase the size of padding between the border and text
# borderpad=5 will increase the distance between the border and the axes
# frameon=False will remove the box around the text

anchored_text = AnchoredText("Test", loc=2)
ax.plot(x,y)
ax.add_artist(anchored_text)

plt.show()

enter image description here

Answered By: Anake

The question is quite old but as there is no general solution to the problem till now (2019) according to Add loc=best kwarg to pyplot.text(), I’m using legend() and the following workaround to obtain auto-placement for simple text boxes:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpl_patches

x = np.linspace(-1,1)
fig, ax = plt.subplots()
ax.plot(x, x*x)

# create a list with two empty handles (or more if needed)
handles = [mpl_patches.Rectangle((0, 0), 1, 1, fc="white", ec="white", 
                                 lw=0, alpha=0)] * 2

# create the corresponding number of labels (= the text you want to display)
labels = []
labels.append("pi = {0:.4g}".format(np.pi))
labels.append("root(2) = {0:.4g}".format(np.sqrt(2)))

# create the legend, supressing the blank space of the empty line symbol and the
# padding between symbol and label by setting handlelenght and handletextpad
ax.legend(handles, labels, loc='best', fontsize='small', 
          fancybox=True, framealpha=0.7, 
          handlelength=0, handletextpad=0)
plt.show()

The general idea is to create a legend with a blank line symbol and to remove the resulting empty space afterwards. How to adjust the size of matplotlib legend box? helped me with the legend formatting.

Example plot with automatically positioned text box

Answered By: Chipmuenk
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.