The approach you took is in principle correct. However, just like when placing a legend with bbox_to_anchor
, the location is determined as an interplay between bbox_to_anchor
and loc
. Most of the explanation in the above linked answer applies here as well.
The default loc
for inset_axes
is loc=1
("upper right"). This means that if you you specify bbox_to_anchor=(0.4,0.1)
, those will be the coordinates of the upper right corner, not the lower left one.
You would therefore need to specify loc=3
to have the lower left corner of the inset positionned at (0.4,0.1)
.
However, specifying a bounding as a 2-tuple only makes sense if not specifying the width and height in relative units ("30%"
). Or in other words, in order to use relative units you need to use a 4-tuple notation for the bbox_to_anchor
.
In case of specifying the bbox_to_anchor
in axes units one needs to use the bbox_transform
argument, again, just as with legends explained here, and set it to ax.transAxes
.
plt.figure(figsize=(6,3))
ax = plt.subplot(221)
ax.set_title("100%, (0.5,1-0.3,.3,.3)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="100%", height="100%", loc='upper left',
bbox_to_anchor=(0.5,1-0.3,.3,.3), bbox_transform=ax.transAxes)
ax = plt.subplot(222)
ax.set_title("30%, (0.5,0,1,1)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
bbox_to_anchor=(0.5,0,1,1), bbox_transform=ax.transAxes)
Find a complete example on the matplotlib page: Inset Locator Demo
Another option is to use InsetPosition
instead of inset_axes
and to give an existing axes a new position. InsetPosition
takes the x and y coordinates of the lower left corner of the axes in normalized axes coordinates, as well as the width and height as input.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
fig, ax= plt.subplots()
iax = plt.axes([0, 0, 1, 1])
ip = InsetPosition(ax, [0.4, 0.1, 0.3, 0.7]) #posx, posy, width, height
iax.set_axes_locator(ip)
iax.plot([1,2,4])
plt.show()
Finally one should mention that from matplotlib 3.0 on, you can use matplotlib.axes.Axes.inset_axes
import matplotlib.pyplot as plt
plt.figure(figsize=(6,3))
ax = plt.subplot(221)
ax.set_title("ax.inset_axes, (0.5,1-0.3,.3,.3)")
ax.plot([0,4], [0,10])
axins = ax.inset_axes((0.5,1-0.3,.3,.3))
plt.show()
The result is roughly the same, except that mpl_toolkits.axes_grid1.inset_locator.inset_axes
allows for a padding around the axes (and applies it by default), while Axes.inset_axes
does not have this kind of padding.