Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subtitles within Matplotlib legend

I am doing some plotting with matplotlib, and I have a legend which tells the viewer which sensors the points were recorded with. There are multiple sensors of multiple types, and I'd like to have subtitles within the legend to tell the viewer what kind of sensor each group is. I have a working solution, but it's a bit of a hack, shown here:

enter image description here

When the legend is created, it accepts two important arguments: a list of legend markers, and a list of legend labels. My current solution is to set the subtitle marker to be a white box with a white outline, and have the subtitle lable be surrounded by two newline characters. It looks alright, but it would look much more professional if the subtitles were not indented. Two workarounds I have tried have been setting the subtitle's marker to None, and also setting the subtitle's marker to the desired subtitle string and its label to an empty string. Neither have worked. Does anyone have any experience with this? Thanks so much.

like image 296
Jabberwock Stomp Avatar asked Jul 19 '16 15:07

Jabberwock Stomp


People also ask

How to put a subtitle in Matplotlib?

Adding a Subtitle to a Matplotlib Plot While Matplotlib doesn't actually offer a subtitle method, it does offer a . suptitle() method. This method acts as a higher-level title. We can then use the regular title as a subtitle.

How do you plot a subtitle in Python?

The shortest answer to your subtitle question is: There is a built-in suptitle() function. Thus, combining suptitle()/title() is similar to the more intuitively named title()/subtitle() .


1 Answers

The best I could come up with is to make a custom handler for a string.

import matplotlib.pyplot as plt
import matplotlib.text as mtext


class LegendTitle(object):
    def __init__(self, text_props=None):
        self.text_props = text_props or {}
        super(LegendTitle, self).__init__()

    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        title = mtext.Text(x0, y0, r'\underline{' + orig_handle + '}', usetex=True, **self.text_props)
        handlebox.add_artist(title)
        return title


[line1] = plt.plot(range(10))
[line2] = plt.plot(range(10, 0, -1), 'o', color='red')
plt.legend(['Title 1', line1, 'Title 2', line2], ['', 'Line 1', '', 'Line 2'],
           handler_map={basestring: LegendTitle({'fontsize': 18})})

plt.show()

output

I based this on the example in http://matplotlib.org/users/legend_guide.html.

like image 199
pelson Avatar answered Oct 14 '22 20:10

pelson