I'd like to replace a matplotlib legend with a new one, but keep the same (possibly arbitrary) location of the legend being replaced.
Why won't the following code work?
import matplotlib.pyplot as plt plt.plot(range(10)) ax = plt.gca() leg = plt.legend(['a'], loc='lower left') bb = leg.get_bbox_to_anchor().inverse_transformed(ax.transAxes) plt.legend(['b'], bbox_to_anchor=bb)
To answer the question why the code in the question wouldn't work:
The legend's position is determined only at runtime when the figure is drawn. Additionally the bbox_to_anchor is not set, so it will be the complete axes ((0,0,1,1)
).
What you can do is first draw the canvas and then obtain the window extent
ax.figure.canvas.draw()
bb = leg.get_window_extent().inverse_transformed(ax.transAxes)
This however will not give you the correct position (only close to it).
Now a possible solution might be not to replace the legend, but instead only update it's content:
import matplotlib.pyplot as plt
plt.plot(range(10))
ax = plt.gca()
leg = plt.legend(['a'], loc='lower left')
leg.texts[0].set_text("b")
plt.show()
Otherwise, if updating is not an option, you would need the bbox_to_anchor and the loc parameter from the old legend:
import matplotlib.pyplot as plt
plt.plot(range(10))
ax = plt.gca()
leg = plt.legend(['a'], loc='lower left', bbox_to_anchor=(0.5,0.5))
bb = leg.get_bbox_to_anchor().inverse_transformed(ax.transAxes)
plt.legend(['b'], bbox_to_anchor=bb, loc=leg._loc_real)
plt.show()
This may still fail in cases, where mode has been set to "expand". It is also only accurate when the same fancybox paramters are used to create the new legend.