mrclary
mrclary

Reputation: 567

How to replace matplotlib legend and keep same location?

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)

Upvotes: 1

Views: 1188

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339340

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.

Upvotes: 2

litepresence
litepresence

Reputation: 3277

unless I'm misunderstanding, just do:

import matplotlib.pyplot as plt

plt.plot(range(10))
ax = plt.gca()

location = 'lower left'

while 1:

    plt.legend(['a'], loc=location)
    plt.pause(1)
    plt.legend(['b'], loc=location)
    plt.pause(1)

Upvotes: 0

Related Questions