From the documentation:
The default transform specifies that text is in data coords, alternatively, you can specify text in axis coords (0,0 is lower-left and 1,1 is upper-right). The example below places text in the center of the axes:
>>> text(0.5, 0.5, 'matplotlib', horizontalalignment='center', ... verticalalignment='center', transform=ax.transAxes)
Can I instead use both data and axis coords? For x and y respectively.
Example code:
import random
import matplotlib.pyplot as plt
values = [random.randint(2,30) for _ in range(15)]
plt.violinplot(values, positions=[1])
# This might place the text outside the figure
plt.gca().text(1, 30, "Text")
# I would like to use axis coords for y instead of data coords. Example call
# would be something like this:
# text_mixed_coords(xdata=1, yaxis=0.9, "Text")
plt.savefig("plot.png")
See also: Putting text in top left corner of matplotlib plot
This is known as a "blended transformation"
you can create a blended transformation that uses the data coordinates for the x axis and axes coordinates for the y axis, like so:
import matplotlib.transforms as transforms
trans = transforms.blended_transform_factory(ax.transData, ax.transAxes)
In your minimal example:
import random
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
fig, ax = plt.subplots()
values = [random.randint(2,30) for _ in range(15)]
ax.violinplot(values, positions=[1])
# the x coords of this transformation are data, and the
# y coord are axes
trans = transforms.blended_transform_factory(
ax.transData, ax.transAxes)
ax.text(1, 0.9, "Text", transform=trans)
plt.savefig("plot.png")
Also worth noting this from the matplotlib tutorial which makes it a little easier in this particular case:
Note:
The blended transformations where x is in data coords and y in axes coordinates is so useful that we have helper methods to return the versions mpl uses internally for drawing ticks, ticklabels, etc. The methods are
matplotlib.axes.Axes.get_xaxis_transform()
andmatplotlib.axes.Axes.get_yaxis_transform()
. So in the example above, the call toblended_transform_factory()
can be replaced byget_xaxis_transform
:trans = ax.get_xaxis_transform()