7

I am using Matplotlib to basically draw a 'picture', not for plotting data.

In the 'picture' I use plt.annotate to label certain parts of the picture.

I now want to make a completely custom legend to indicate the meaning of the symbols.

Is there a way to define custom handles and labels, where the handles must be alphanumeric letters instead of the normal markers like '*' or 'o'.

Is this possible or must I construct the legend manually using plt.annotation?

2
  • You can define you own legend keys. Take a look at this answer. Commented Feb 26, 2015 at 14:41
  • Thanks, but that answer explains how to use different shapes as legend keys. I am not sure how to implement alphanumeric letters using that answer. Commented Feb 26, 2015 at 14:57

2 Answers 2

17

There are a lot of ways to do it, but it's probably easiest to use a proxy artist in this case. You can use arbitrary text as a marker, so it's fairly easy to have fake Line2D's show labels instead of lines.

As an example (the bulk of this is the relatively "fancy" call to annotate):

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

def main():
    labels = ['A', 'B', 'C']
    positions = [(2, 5), (1, 1), (4, 8)]
    descriptions = ['Happy Cow', 'Sad Horse', 'Drooling Dog']

    # Plot the data, similar to what you described...
    fig, ax = plt.subplots()
    ax.imshow(np.random.random((10, 10)), interpolation='none')
    for label, xy in zip(labels, positions):
        ax.annotate(label, xy, xytext=(20, 20), size=15,
                    textcoords='offset points',
                    bbox={'facecolor':'white'},
                    arrowprops={'arrowstyle':'->'})

    # Create a legend with only labels
    proxies = [create_proxy(item) for item in labels]
    ax.legend(proxies, descriptions, numpoints=1, markerscale=2)

    plt.show()

def create_proxy(label):
    line = matplotlib.lines.Line2D([0], [0], linestyle='none', mfc='black',
                mec='none', marker=r'$\mathregular{{{}}}$'.format(label))
    return line

main()

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Great! Thanks for the effort in your answer.
2

In most cases you probably also want to illustrate elements on the graphic with color in your custom legend. In this case I would simply use matplotlib's own functions, than you also do not need to write your own complex function.

import matplotlib 

red_line = matplotlib.lines.Line2D([], [], color='red',markersize=100, label='Blue line')


blue_line = matplotlib.lines.Line2D([], [], color='blue', markersize=100, label='Green line')
purple_line = matplotlib.lines.Line2D([], [], color='purple', markersize=100, label='Green line')

handles = [blue_line,red_line, purple_line]
labels = [h.get_label() for h in handles] 

ax.legend(handles=handles, labels=labels)  
plt.show()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.